使用OpenSSL无法正确解密AES-256-CBC加密数据问题求助
解决OpenSSL解密报错:
error:0606508A:digital envelope routines:EVP_DecryptFinal_ex:data not multiple of block length 我之前也碰到过这个报错,核心原因其实很明确:你用的填充规则和第三方加密时用的不匹配,导致解密时数据长度不符合AES-CBC的块大小要求(AES块固定是16字节)。
问题出在哪?
你代码里指定了OPENSSL_ZERO_PADDING(零填充),但能在线解密成功,说明第三方加密时用的是行业通用的PKCS#7(或PKCS#5)填充,这两种填充逻辑完全不一样:
- PKCS#7填充:如果数据不够16字节,就填充
n个值为n的字节(比如缺3字节就填3个0x03);要是刚好凑够16字节倍数,还会额外填16个0x10,方便解密时识别并移除填充内容。 - 零填充:只填0字节,这种方式几乎没人用,还容易和原始数据末尾的0混淆。
用零填充去解PKCS#7填充的加密数据,自然会触发“数据不是块长度倍数”的报错。
修复代码很简单
把OPENSSL_ZERO_PADDING换成OPENSSL_RAW_DATA(或者直接省略这个参数,因为openssl_decrypt默认就是自动处理PKCS填充的),同时保证密钥和IV的十六进制转二进制是对的:
$result = openssl_decrypt( $bin, 'AES-256-CBC', hex2bin($this->key), OPENSSL_RAW_DATA, // 自动识别并移除PKCS填充 hex2bin($this->iv) ); if (!$result) { while ($msg = openssl_error_string()) { echo "ERROR: " . $msg; } }
额外要检查的几个点
- 确认
$bin是纯二进制的加密数据,没有被Base64之类的编码过——如果是Base64格式的,得先base64_decode($bin)再解密。 - 核对密钥和IV的长度:AES-256的密钥必须是32字节(对应64位十六进制字符串),IV必须是16字节(对应32位十六进制字符串),长度不对的话解密肯定失败。
- 可以先打印
strlen($bin)看看是不是16的整数倍,如果不是,那大概率是加密数据在传输过程中被截断或者编码出错了。
内容的提问来源于stack exchange,提问作者ineersa
相关产品推荐
相关产品推荐

