我已经阅读了一般建议: mcrypt is deprecated, what is the alternative?和 PHP7.1 mcrypt alternative
并测试了以下解决方案: Migrating mcrypt with Blowfish and ECB to OpenSSL和 php: mcrypt_encrypt to openssl_encrypt, and OPENSSL_ZERO_PADDING problems
他们没有用。这是我使用的代码:
$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));
使用“ DES-EDE3-CBC”之类的加密方法确实有效。但是我无法更改所使用的加密。我必须将旧代码迁移到新代码。有时会使用少于16个字符的键。
有什么建议吗?
答案 0 :(得分:2)
首先,OPENSSL_NO_PADDING
不应该与openssl_encrypt()
一起使用。 Its documentation提到OPENSSL_ZERO_PADDING
,(令人困惑地)表示“无填充”。那就是你想要的。
OPENSSL_NO_PADDING
是intended for use with asymmetric cryptography。碰巧的是,它的值3等于OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
。这就是为什么您不正确地使用它而不造成后果的原因(在这种情况下)。
您的密文有所不同,因为默认情况下,openssl_encrypt()
模式下的功能bf-ecb
会在密钥的长度小于16个字节时用\0
填充密钥。河豚不需要这样做,mcrypt_encrypt()
则不需要。为了关闭该行为,请在调用OPENSSL_DONT_ZERO_PAD_KEY
时使用标志openssl_encrypt()
。由于似乎未记录此标志,因此您必须前往the source code进行了解:-)。或阅读Bug #72362 OpenSSL Blowfish encryption is incorrect for short keys。
这样,openssl_encrypt()
的正确调用变为:
$opts = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING | OPENSSL_DONT_ZERO_PAD_KEY;
$encrypted_openssl = openssl_encrypt($message_padded, "bf-ecb", $key, $opts);
测试:
$ php bf.php
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ
My secret message => JPO/tvAqFD2KCTqfv0l8uWLfPUWdZIxQ