繁体   English   中英

openssl_encrypt没有向量的AES加密

[英]openssl_encrypt AES encrypt with out vector

我需要令牌来访问某些源。 源提供者给了我一个Java示例,向我展示了如何创建它。 它是如何加密文本的:

private static final String ALGO = "AES";                   
public static String encrypt(byte[] keyValue, String token_text) throws Exception {                 
    Key key = new SecretKeySpec(keyValue, ALGO);
    Cipher c = Cipher.getInstance(ALGO);
    c.init(Cipher.ENCRYPT_MODE, key);

    byte[] bytes = c.doFinal(token_text.getBytes());
    byte[] buf = Base64.encodeBase64(bytes);

    return new String(buf); 
}

我希望将此Java程序的价格翻译为php.So,这是我的代码:

public static function generate_token($token_text, $key) {
        $iv = self::hex_to_str("00000000000000000000000000000000");
        $token = openssl_encrypt($token_text, "AES-128-CBC", $key, 0, $iv);
        return $token;
    }

    private static function hex_to_str($hex)
    {
            $string='';
            for ($i=0; $i < strlen($hex)-1; $i+=2)
            {
                $string .= chr(hexdec($hex[$i].$hex[$i+1]));
            }
            return $string;
    }

但是我无法得到相同的结果。 我四处搜寻。 它看起来像没有向量的cipher.init。 如果我对openssl_encrypt做同样的事情,它将给我一个错误:

openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended

有人说Cipher的默认向量是0。我尝试过,仍然无法获得相同的结果,但是非常接近:

java:v8GhW0lu8DzNyqsfQTg4g7H6pwXCAAgy9vqFdz5OmXY =

的PHP:v8GhW0lu8DzNyqsfQTg4g6If77f + 8YVCcq8VcQGNe68 =

我在这里呆了一整天。 如果有人可以帮助,我将不胜感激。

# java -version
openjdk version "1.8.0_101"
OpenJDK Runtime Environment (build 1.8.0_101-b13)
OpenJDK 64-Bit Server VM (build 25.101-b13, mixed mode)

# php -v
PHP 5.6.24 (cli) (built: Jul 21 2016 07:42:08) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies

在Java端使用SunJCE-Provider的假设下,默认模式为ECB模式,默认填充为PKCS5Padding,即Cipher.getInstance("AES")Cipher.getInstance("AES/ECB/PKCS5Padding")例如参见https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#ciphertrans

ECB模式不使用IV。 因此,您必须在PHP中替换generate_token-method

$iv = self::hex_to_str("00000000000000000000000000000000");
$token = openssl_encrypt($token_text, "AES-128-CBC", $key, 0, $iv);

$token = openssl_encrypt($token_text, "AES-128-ECB", $key, 0);

例:

encrypt("This is the key!".getBytes(), "This is a plain text that needs to be encrypted...");

提供

fLSh/HoQkrsIVBtZJVnuIRqcz4ztUBDkDG9Pi3xe49Q9hh9zDzWZDRHEO70ixfLf2WbWYSeDOQ/ONFTWHW9i0Q==

这与PHP代码的结果相同(对于相同的键和纯文本)。

通常,如果您有多个块,则ECB模式是不安全的(根据示例,我推断您的令牌至少包含两个块)。 然后,更好的选择是CBC模式或GCM模式,请参见例如https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryptionhttps://security.stackexchange .com / questions / 6500 / aes-ecb-mode-for-single-block-random-data-encryption 但是由于Java加密方法似乎是您的参考,因此可能无法更改它。

编辑:

Java密码类自动确定密钥大小,是否必须使用AES-128,AES-192或AES-256。 因此,您还必须知道Java代码上下文中密钥的大小。 如果密钥大小为16字节,那么AES-128-ECB的选择是正确的,否则您必须相应地调整PHP代码(例如,对于24字节或32字节密钥大小,为AES-192-ECB或AES-256-ECB,分别)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM