将 mcrypt AESencrypt 函数转换为 openssl 但不起作用
Posted
技术标签:
【中文标题】将 mcrypt AESencrypt 函数转换为 openssl 但不起作用【英文标题】:Convert mcrypt AESencrypt function to openssl but not working 【发布时间】:2021-10-28 04:05:15 【问题描述】:这是我在 php 5.6 中完美运行的旧代码
function AESencrypt($decrypted, $password, $salt)
$block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$padding = $block - (strlen($decrypted) % $block);
$decrypted .= str_repeat(chr($padding), $padding);
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $password, $decrypted , MCRYPT_MODE_CBC, $password));
$encrypted = hash('SHA256', $encrypted.'|'.$salt, true);
return strToHex($encrypted);
$hashkey= AESencrypt("input","password", "salt");
然后我切换到 PHP 7.4,但该功能无法正常工作,因此我尝试将其转换为 OpenSSL,但它不会产生 有效的哈希键
新代码在这里
function AESencrypt($decrypted, $password, $salt)
$padding = 16 - (strlen($salt) % 16);
$salt .= str_repeat("\0", $padding);
$block = 16;
$padding = $block - (strlen($decrypted) % $block);
$decrypted .= str_repeat(chr($padding), $padding);
$cipher = (mb_strlen($password, '8bit') <= 8) ? 'aes-128-cbc' : 'aes-256-cbc';
$encrypted = base64_encode(
openssl_encrypt($decrypted, $cipher, $password, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $password)
);
$encrypted = hash('SHA256', $encrypted.'|'.$salt, true);
return strToHex($encrypted);
$hashkey = AESencrypt("input","password", "salt");
strToHex()在这里
function strToHex($string)
$hex = '';
for ($i=0; $i<strlen($string); $i++)
$ord = ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0'.$hexCode, -2);
return strToUpper($hex);
我已经尝试了上一个问题中给出的解决方案,但它仍然显示 invalid hash key
【问题讨论】:
您的填充不同。这也是一个非常奇怪的哈希函数。 【参考方案1】:在旧代码中,salt 没有被填充,并且设计用于 AES-128,即 16 字节密钥。如果在新代码中删除了盐的填充,则没有 AES-256 用于大于 8 (?!) 字节的密钥并应用 16 字节的密钥,结果是相同的。
另外,新代码可以写得更紧凑:
使用隐式 PKCS#7 填充而不是显式填充(删除OPENSSL_NO_PADDING
)
使用隐式 Base64 编码而不是显式编码(删除 OPENSSL_RAW_DATA
)
使用内置函数bin2hex()
,而不是自定义函数strToHex()
。但即使这样也可以避免,因为hash()
默认返回十六进制编码的结果:
function AESencrypt($decrypted, $password, $salt)
$encrypted = openssl_encrypt($decrypted, 'aes-128-cbc', $password, 0, $password);
$hash = hash('SHA256', $encrypted . '|' . $salt);
return strToUpper($hash);
$result = AESencrypt("The quick brown fox jumps over the lazy dog", "0123456789abcdef", "01234567");
print($result . PHP_EOL); // 7A8D13F38E4A63F821A75FAA8C7B879C7BCC99B34102BAA731015735F5F5EAD3
该方法的目的不明确。最终的散列使处理不可逆,即无法解密。也许用这个来实现一个密钥推导。但是,有更多经过验证的方法,例如Argon2(基于密码)或 HKDF(基于密钥)。
【讨论】:
以上是关于将 mcrypt AESencrypt 函数转换为 openssl 但不起作用的主要内容,如果未能解决你的问题,请参考以下文章
CryptoJS 中 CFB 模式中的 mcrypt_encrypt 函数
PHP:OpenSSL 等价于 mcrypt:MCRYPT_3DES?