使用相同密钥和数据时,PHP与Python的AES-256-CBC加密结果为何不同?
AES-256-CBC跨PHP/Python加密结果不一致的原因及解决方法
核心问题:密钥与IV的生成方式差异
你的代码里,PHP和Python生成密钥、IV的逻辑看似一致,实则存在本质区别:
- PHP端:
hash('sha256', $secret_key)默认返回十六进制字符串(每个字节用两个字符表示),substr(..., 0, 32)取的是32个十六进制字符,仅对应16字节的密钥,但AES-256需要32字节的密钥,直接导致密钥长度不足;同理,IV取16个十六进制字符(仅8字节),不符合CBC模式16字节IV的要求。 - Python端:
sha256(...).digest()返回的是原始字节串,[:32]取的是32字节密钥、[:16]取的是16字节IV,完全符合加密算法的要求。 - 额外问题:PHP原代码中
openssl_encrypt默认返回base64编码后的字符串,你又手动执行了一次base64_encode,导致做了两次base64编码,结果自然和Python不一致。
修正后的PHP代码
调整hash函数参数获取原始字节串,同时修正openssl_encrypt的输出模式:
<?php $plaintextstr = 'AAAAAAAAAAAAAAAA'; $encrypt_method = "AES-256-CBC"; $secret_key = "SSSSSSSSSSSS"; $secret_iv = "LLLLLLLLLLLL"; // 生成32字节的AES-256密钥,第三个参数true让hash返回原始字节串 $key = substr(hash('sha256', $secret_key, true), 0, 32); // 生成16字节的CBC模式IV $iv = substr(hash('sha256', $secret_iv, true), 0, 16); // OPENSSL_RAW_DATA让函数返回原始加密字节串,避免自动base64编码 $encrypted_str = openssl_encrypt($plaintextstr, $encrypt_method, $key, OPENSSL_RAW_DATA, $iv); echo base64_encode($encrypted_str); ?>
验证说明
修正后,两端的加密逻辑完全对齐:
- 密钥、IV均为SHA256哈希后的原始字节截取,长度符合算法要求
- 填充逻辑统一为PKCS7(
openssl_encrypt默认使用PKCS7填充,与Python的pad函数一致) - 最终仅执行一次base64编码
此时PHP与Python的加密结果将完全一致。
内容的提问来源于stack exchange,提问作者Yeivicr
相关产品推荐
相关产品推荐

