简体   繁体   中英

openssl_encrypt AES encrypt with out vector

I need a token to access some source. The source provider gave me a java example that show me how to create it. Here is how it encrypt text:

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); 
}

I wish to translate this pice of java program to php.So, here is my code:

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;
    }

But I can't get same result. I searched around. It looks like cipher.init called without vector. If i do the same thing to openssl_encrypt, it will gave me an error:

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

Some one said the default vector for Cipher is 0. I tried so, still can't get the same result, but very close:

java: v8GhW0lu8DzNyqsfQTg4g7H6pwXCAAgy9vqFdz5OmXY=

php : v8GhW0lu8DzNyqsfQTg4g6If77f+8YVCcq8VcQGNe68=

I am stuck here for a whole day. I would be very grateful if anyone can help.

# 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

Under the assumption that the Java side uses the SunJCE-Provider the default mode is the ECB-mode and the default padding is the PKCS5Padding ie Cipher.getInstance("AES") is identical to Cipher.getInstance("AES/ECB/PKCS5Padding") see eg https://docs.oracle.com/javase/8/docs/technotes/guides/security/SunProviders.html#ciphertrans .

The ECB-mode doesn't use an IV. Thus, you have to replace in your PHP generate_token-method

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

with

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

Example:

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

provides

fLSh/HoQkrsIVBtZJVnuIRqcz4ztUBDkDG9Pi3xe49Q9hh9zDzWZDRHEO70ixfLf2WbWYSeDOQ/ONFTWHW9i0Q==

which is identical to the result of the PHP code (for the same key and plain text).

Generally, the ECB-mode is not secure if you have more than one block (from your examples I infer that your token consists of at least two blocks). Then, a better choice would be the CBC- or GCM-mode, see eg https://crypto.stackexchange.com/questions/20941/why-shouldnt-i-use-ecb-encryption and https://security.stackexchange.com/questions/6500/aes-ecb-mode-for-single-block-random-data-encryption . But since the Java encrypt-method seems to be your reference there is probably no way to change it.

EDIT:

The Java cipher-class determines automatically with the keysize if AES-128, AES-192 or AES-256 must be used. Therefore, you also have to know the size of the key in the context of the Java code. If the keysize is 16 byte then the choice of AES-128-ECB is correct, otherwise you have to adjust your PHP code accordingly (eg AES-192-ECB or AES-256-ECB for a 24 byte or a 32 byte keysize, respectively).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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