无法在PHP中将mcrypt升级为openssl解密
我正在将一个旧式应用程序从PHP7.0升级到7.2,当我将mcrypt切换到openssl时,我的解密功能不起作用 我尝试了现有的答案,如,和GIST,但我仍然无法使代码工作 谁能解释一下我做错了什么 旧代码无法在PHP中将mcrypt升级为openssl解密,php,openssl,mcrypt,Php,Openssl,Mcrypt,我正在将一个旧式应用程序从PHP7.0升级到7.2,当我将mcrypt切换到openssl时,我的解密功能不起作用 我尝试了现有的答案,如,和GIST,但我仍然无法使代码工作 谁能解释一下我做错了什么 旧代码 function decrypt($value, $key) { $ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); $iv = substr($value, 0, $ivLength)
function decrypt($value, $key) {
$ivLength = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = substr($value, 0, $ivLength);
return rtrim(
mcrypt_decrypt(
MCRYPT_RIJNDAEL_128,
hash('sha256', $key, true),
substr($value, $ivLength),
MCRYPT_MODE_CBC,
$iv
),
"\0"
);
}
新代码(不使用现有输入)
对于上下文,以下是旧代码如何加密值:
function encrypt($value, $key) {
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_URANDOM);
return $iv . mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
hash('sha256', $key, true),
$value,
MCRYPT_MODE_CBC,
$iv
);
}
此外,
$value
中的原始值在新代码中输出到错误日志时的长度是旧代码的两倍,并且看起来类似,但包含更多字符。这里的主要问题是密钥大小。您使用返回256位哈希的SHA256创建密钥,因此您将AES/Rijndael与256位密钥一起使用
Rijndael-128中的数字定义了块大小,密钥大小由我们使用的密钥长度决定。AES-128中的数字定义了密钥大小(块大小为常数,128位),如果实际密钥长度不同于此数字,则会缩短或扩展密钥(零字节)以适合所选密钥大小
这意味着您的mcrypt
代码在CBC模式下使用带256位密钥的Rijndael-128(AES)。等效的openssl
是AES-256-CBC,如果我们使用此算法,那么mcrypt
和openssl
应该产生兼容的结果
function decrypt_mcrypt_with_openssl($value, $key) {
$iv = substr($value, 0, 16);
$ciphertext = substr($value, 16);
$key = hash('sha256', $key, true);
$plaintext = openssl_decrypt(
$ciphertext, 'AES-256-CBC', $key,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv
);
return rtrim($plaintext, "\0");
}
SHA256不适合作为密钥派生函数。如果您是从密码派生密钥,则可以使用随机salt和足够高的迭代次数。或者您可以使用创建一个加密安全的伪随机密钥
我认为最好完全停止使用
mcrypt
,只使用openssl
。Mcrypt不支持PKCS7填充,它不提供任何算法,并且不再进行维护 这里的主要问题是密钥大小。您使用返回256位哈希的SHA256创建密钥,因此您将AES/Rijndael与256位密钥一起使用
Rijndael-128中的数字定义了块大小,密钥大小由我们使用的密钥长度决定。AES-128中的数字定义了密钥大小(块大小为常数,128位),如果实际密钥长度不同于此数字,则会缩短或扩展密钥(零字节)以适合所选密钥大小
这意味着您的mcrypt
代码在CBC模式下使用带256位密钥的Rijndael-128(AES)。等效的openssl
是AES-256-CBC,如果我们使用此算法,那么mcrypt
和openssl
应该产生兼容的结果
function decrypt_mcrypt_with_openssl($value, $key) {
$iv = substr($value, 0, 16);
$ciphertext = substr($value, 16);
$key = hash('sha256', $key, true);
$plaintext = openssl_decrypt(
$ciphertext, 'AES-256-CBC', $key,
OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
$iv
);
return rtrim($plaintext, "\0");
}
SHA256不适合作为密钥派生函数。如果您是从密码派生密钥,则可以使用随机salt和足够高的迭代次数。或者您可以使用创建一个加密安全的伪随机密钥
我认为最好完全停止使用
mcrypt
,只使用openssl
。Mcrypt不支持PKCS7填充,它不提供任何算法,并且不再进行维护 我很确定旧的加密和新的解密将不兼容。为什么要对密钥使用不同的方法<代码>附加_键也未定义anywhere@Devon哎呀,那不应该在那里,它已经被重构了。我把它从代码中删除了。你还在旧代码中散列密钥encrypt@Devon抢手货我更新了代码,但仍然不起作用,返回一个空字符串。我很确定旧的加密和新的解密将彼此不兼容。为什么对密钥使用不同的方法<代码>附加_键也未定义anywhere@Devon哎呀,那不应该在那里,它已经被重构了。我把它从代码中删除了。你还在旧代码中散列密钥encrypt@Devon抢手货我更新了代码,但仍然不起作用,返回一个空字符串。你是迄今为止我遇到的最好的程序员@t.m.adam。是的,结果是对的。但愿我有你做我的老师。谢谢。你是迄今为止我遇到的最好的程序员@t.m.adam。是的,结果是对的。但愿我有你做我的老师。谢谢