AES-128解密Python转PHP失败:digital envelope routines错误
解决AES-128 CBC解密PHP报错"bad decrypt"的问题
问题原因
PHP的openssl_decrypt函数默认会启用PKCS#7填充验证,但你的Python代码使用PyCryptodome解密时,并未进行填充验证(直接解密原始密文数据)。当密文末尾不符合PKCS#7填充规则时,OpenSSL就会抛出error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt错误。
修正后的PHP代码
只需在openssl_decrypt的参数中添加OPENSSL_ZERO_PADDING禁用填充验证,同时保留OPENSSL_RAW_DATA确保输出原始二进制数据:
<?php $IV = str_repeat("\x00", 16); $key = str_repeat("\x00", 16); // 可替换为你的目标密文,此处用Python示例中的密文测试 $Enc_PICC_Data = hex2bin('38308EB36348ED39599ED6AFB1602F9F'); // 组合参数:原始数据输出 + 禁用填充验证 $ciphertext = openssl_decrypt($Enc_PICC_Data, 'aes-128-cbc', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $IV); if ($ciphertext === false) { echo "OpenSSL error: " . openssl_error_string(); } else { echo "解密成功<br>"; $PICCDataTag = bin2hex(substr($ciphertext, 0, 1)); $UID = bin2hex(substr($ciphertext, 1, 7)); $SDMReadCtr = bin2hex(substr($ciphertext, 8, 3)); echo "解密后的PICCData: " . bin2hex($ciphertext) . "<br>"; echo "PICCDataTag: " . $PICCDataTag . "<br>"; echo "UID : " . $UID . "<br>"; echo "SDMReadCtr : " . $SDMReadCtr . "<br>"; } ?>
关键说明
OPENSSL_ZERO_PADDING:禁用OpenSSL默认的PKCS#7填充验证,让解密逻辑和Python代码完全对齐,直接处理原始解密结果。- 若密文使用了自定义填充(如代码注释中的RandomPadding),解密后的数据末尾会包含填充内容,可根据业务需求自行截断处理。
内容的提问来源于stack exchange,提问作者Benni
相关产品推荐
相关产品推荐

