PHP代码解密失败求助:openssl_decrypt函数返回false
排查PHP openssl_decrypt()返回false(bad decrypt)的常见原因
1. 加密/解密核心参数不匹配
- 必须使用完全相同的加密算法(如AES-256-CBC、AES-128-GCM等),加密和解密的算法字符串要一字不差,比如加密用
AES-256-CBC,解密不能写成AES-128-CBC。 - 密钥(key)必须完全一致:注意密钥长度要匹配算法要求,比如AES-256需要32字节密钥,AES-128需要16字节,若密钥长度不符,OpenSSL会自动截断或补全,直接导致解密失败。
2. IV处理错误
- 你存储的IV是十六进制字符串,解密时必须先通过
hex2bin()转成原始二进制数据,不能直接把十六进制字符串传入openssl_decrypt的$iv参数。 - IV长度要符合算法的块大小要求:比如AES的块大小是16字节,对应32位十六进制字符串,你的示例IV
86f8589c55d009da3f46e039a1ee1218是32位,长度没问题,但要确保解密时做了进制转换。
3. 密文处理错误
- 存储的密文是十六进制格式,解密前必须用
hex2bin()转成二进制数据,不能直接传入密文字符串。如果加密时用的是base64编码,解密则要对应使用base64_decode(),必须和加密流程的编码方式严格对应。
4. 填充方式与选项不匹配
- OpenSSL默认填充方式为
PKCS7,如果加密时手动指定了其他填充方式(如OPENSSL_ZERO_PADDING),解密时必须指定相同的填充方式,否则会触发bad decrypt错误。 - 加密和解密的
$options参数(比如OPENSSL_RAW_DATA)要完全一致,比如加密用了OPENSSL_RAW_DATA输出原始二进制密文,解密时也要传这个参数。
5. 数据存储/读取损坏
- 检查从数据库读取的
iv:encrypted_data字符串是否完整,有没有被截断、转义(比如MySQL的特殊字符转义处理),导致IV或密文缺失。可以直接输出读取后的字符串和加密时生成的原始字符串对比,确认完全一致。
修正示例参考
假设你的加密代码逻辑如下:
$algorithm = 'AES-256-CBC'; $key = 'your-32-byte-secret-key-here'; $raw_data = '患者医疗数据内容'; // 生成符合长度的IV $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($algorithm)); // 加密并输出原始二进制 $encrypted_bin = openssl_encrypt($raw_data, $algorithm, $key, OPENSSL_RAW_DATA, $iv); // 转十六进制拼接后存入数据库 $store_str = bin2hex($iv) . ':' . bin2hex($encrypted_bin);
对应的解密代码必须严格对应:
$algorithm = 'AES-256-CBC'; $key = 'your-32-byte-secret-key-here'; $stored_str = '从数据库读取的iv:encrypted字符串'; // 拆分IV和密文(限制拆分2份,避免密文中含冒号) list($iv_hex, $encrypted_hex) = explode(':', $stored_str, 2); // 转二进制格式 $iv = hex2bin($iv_hex); $encrypted_bin = hex2bin($encrypted_hex); // 解密 $decrypted = openssl_decrypt($encrypted_bin, $algorithm, $key, OPENSSL_RAW_DATA, $iv); if ($decrypted === false) { var_dump(openssl_error_string()); } else { echo $decrypted; }
内容的提问来源于stack exchange,提问作者UJWAL0747
相关产品推荐
相关产品推荐

