我想改进某个使用现已过时的“mcrypt”的 WordPress 插件。相反,我想使用 OpenSSL 库来加密提交的数据,但在加密过程中我遇到了问题,即: openssl_encrypt 函数返回与 mcrypt_encrypt 不同的值,我连接到的系统不会返回我的值正确的数据,并且其所有者无法向我发送我上传到其中的内容的日志:(
我已经搜索了整个互联网,但还没有找到解决方案。我怀疑问题出在填充上,但我找不到解决方案。你能帮忙吗?
下面是我的 PHP 对象 $password、$salt 和 $iv 的内部明显发生了变化
class EncryptDebug{ private $algo = 'sha1'; private $password = 'ab4232goodcf423484422c90c3e4aa7c'; private $salt = 'ascastas54490a31'; private $iv = '8947da32awl55kwj' private $lenght = 16; private function generate_key(){ return hash_pbkdf2( $this->algo , $this->password , $this->salt, 100, $this->lenght, true ); } public function encryptSSL($plaintext){ $key = $this->generate_key(); $ciphertext = base64_encode(openssl_encrypt($plaintext, 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $this->iv)); return str_replace('+', '%2B', $ciphertext); } public function encryptMCRYPT($plaintext){ $key = $this->generate_key(); $ciphertext = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_CBC, $this->iv)); return str_replace('+', '%2B', $ciphertext); } }
忘记提及:OPENSSL_ZERO_PADDING 返回错误。使用 OPENSSL_RAW_DATA 我可以获得与 mcrypt_encrypt 类似的结果,但结局不同,例如:
OpenSSL:rPzVvF7gaPMA4ADAjHUW8Wy1ThTJG%2BVPdcz5iKAkAwrDTTFTcOpWgWOCh9l9JFZ8WcNzMJ868026TkUxcYJMrQ==
MCRYPT:rPzVvF7gaPMA4ADAjHUW8Wy1ThTJG%2BVPdcz5iKAkAwrDTTFTcOpWgWOCh9l9JFZ8UGVfF091Q9bY61mTRg%2BBSg==
在
encryptSSL()
中,当前使用 Base64 编码两次,默认情况下一次是显式编码,一次是隐式编码。因此,必须删除其中一种 Base64 编码,无论是显式编码还是隐式编码。前者是通过删除base64_encode()
调用来实现的,后者是通过设置OPENSSL_RAW_DATA
标志来实现的。此外,mcrypt 使用零填充,PHP/OpenSSL 使用 PKCS#7 填充。因此,为了使
encryptSSL()
给出与encryptMCRYPT()
相同的结果,必须使用零填充。由于 PHP/OpenSSL 不支持零填充,因此必须禁用 PKCS#7 填充(使用 OPENSSL_ZERO_PADDING 标志)并且必须显式实现零填充>.总体:
与:
通过这些更改,两个函数给出相同的结果。
请注意,与 PKCS#7 填充相比,零填充不可靠。
安全性:
请注意,静态 IV 和静态盐是漏洞。相反,两者都将随机生成并与密文一起传递到解密方,通常是串联的(两者都不是秘密的)。
此外,PBKDF2 的迭代次数为 100 通常太小。