I've read the general suggesstions: mcrypt is deprecated, what is the alternative? and PHP7.1 mcrypt alternative
And tested the following solutions: Migrating mcrypt with Blowfish and ECB to OpenSSL and php: mcrypt_encrypt to openssl_encrypt, and OPENSSL_ZERO_PADDING problems
They ain't work. This is my used code:
$message = "My secret message";
$key = "mysecretpasswor"; // <- if you add one more character here, it's working
$iv = "\0\0\0\0\0\0\0\0";
$message_padded = $message;
if(strlen($message_padded) % 8) {
$message_padded = str_pad($message_padded, strlen($message_padded) + 8 - strlen($message_padded) % 8, "\0");
}
$encrypted_mcrypt = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $message, MCRYPT_MODE_ECB, $iv);
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING);
printf("%s => %s\n", $message, base64_encode($encrypted_mcrypt));
printf("%s => %s\n", $message_padded, base64_encode($encrypted_openssl));
Using something like "DES-EDE3-CBC" as encryption method does work. But I cannot change the encryption that's used. I've to migrate the old code to new code. There sometimes keys used, that are shorter than 16 characters.
Any suggestions?
First of all, OPENSSL_NO_PADDING
is not supposed to be used with openssl_encrypt()
. Its documentation mentions OPENSSL_ZERO_PADDING
, which (confusingly) means 'no padding'. That is what you want.
OPENSSL_NO_PADDING
is intended for use with asymmetric cryptography. By coincidence it has a value of 3 which is equal to OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
. This the reason why you can use it incorrectly without consequence (in this case).
Your ciphertexts are different because the function openssl_encrypt()
in bf-ecb
mode by default will pad your key with \0
's if its length is less than 16 bytes. This is not required for blowfish and mcrypt_encrypt()
does not do that. In order to switch off that behavior, use the flag OPENSSL_DONT_ZERO_PAD_KEY
when calling openssl_encrypt()
. Since this flag does not seem to be documented, you will have to go to the source code to learn about it :-). Or read Bug #72362 OpenSSL Blowfish encryption is incorrect for short keys.
With this, the correct invocation of openssl_encrypt()
becomes:
$opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY;
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, $opts);
Testing it:
$ php bf.php
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ