PHP openssl BF-CBC模式解密已加密字符串无返回值问题
问题根因
解密无返回是三个逻辑点共同导致的:
- IV不匹配:代码中使用的
BF-CBC即Blowfish-CBC,属于CBC模式的分组加密算法,解密必须使用和加密时完全一致的初始化向量(IV)。原代码在解密环节调用random_bytes生成了全新的随机IV,和加密时用的IV完全不同,直接导致解密失败。 - IV未随密文传递:加密时生成的随机IV没有和密文绑定返回,解密方根本无法获取加密时使用的正确IV。
- 无可见输出的直接原因:
openssl_decrypt解密失败时会返回布尔值false,PHP中直接echo false不会输出任何可见字符,看起来就像程序没有响应,实际用var_dump打印解密结果就能看到返回值是bool(false)。
修复方案
修复逻辑非常直接:加密时把生成的IV拼接在密文前,统一编码后返回;解密时先从传入的串中拆分出对应长度的IV,再用这个IV执行解密操作。IV不需要保密,只要加密时随机生成即可,和密文一起传递不会降低安全性。
function encrypt($string, $key) { $method = "BF-CBC"; $ivLength = openssl_cipher_iv_length($method); $iv = random_bytes($ivLength); $options = 0; $key = hash("sha256", $key); $ciphertext = openssl_encrypt($string, $method, $key, $options, $iv); // 把IV和密文拼接后base64编码返回 return base64_encode($iv . $ciphertext); } function decrypt($string, $key) { $method = "BF-CBC"; $ivLength = openssl_cipher_iv_length($method); $options = 0; $key = hash("sha256", $key); // 解码后拆分出IV和真实密文 $decodedData = base64_decode($string); $iv = substr($decodedData, 0, $ivLength); $realCiphertext = substr($decodedData, $ivLength); return openssl_decrypt($realCiphertext, $method, $key, $options, $iv); }
测试验证
// 加密foo $encrypted = encrypt("foo", "hfgdhgdfhgfd"); echo "加密结果:" . $encrypted . PHP_EOL; // 解密 $decrypted = decrypt($encrypted, "hfgdhgdfhgfd"); echo "解密结果:" . $decrypted . PHP_EOL;
执行后会正常输出解密后的foo。
注意:之前用旧版
encrypt函数生成的密文无法解密,因为当时加密用的随机IV没有被保存,已经永久丢失。
内容的提问来源于stack exchange,提问作者rileyhopkins
相关产品推荐
相关产品推荐

