我想改进某个使用现已过时的“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
标志)并且必须显式实现零填充.
整体:
$ciphertext = openssl_encrypt($this->zeroPad($plaintext, 16), 'AES-128-CBC', $key, OPENSSL_ZERO_PADDING, $this->iv); // remove base64_encode(), zero pad plaintext, disable PKCS#7 padding
与:
protected function zeroPad($text, $bs) {
$pad = $bs - strlen($text) % $bs;
return ($pad < 16) ? $text . str_repeat("\0", $pad) : $text;
}
通过这些更改,两个函数给出相同的结果。
请注意,与 PKCS#7 填充相比,零填充是不可靠的。
安全:
请注意,静态 IV 和静态盐是漏洞。相反,两者都将随机生成并与密文一起传递给解密方,通常是连接起来的(两者都不是秘密的)。
此外,PBKDF2 的 100 次迭代次数通常太小了。