Python AES加密后PHP解密失败及加密结果不一致问题求助
AES加密Python与PHP跨语言兼容问题排查与修复
问题根源分析
- PHP语法错误:原PHP加密代码中误用了Python风格的
len($plainData),PHP中需改为strlen(),该错误会导致填充逻辑失效;同时openssl_encrypt默认启用PKCS7填充,即使手动补0,也会被二次填充,最终导致加密结果变长。 - 填充方式不匹配:Python代码使用零填充(Null Padding),而PHP默认采用PKCS7填充,这是解密失败、加密结果不一致的核心原因。
- Python填充逻辑不完善:当明文长度刚好是块大小的整数倍时,当前代码不会添加任何填充,不符合零填充的标准规范(此时应填充一个完整块,否则解密时无法区分结尾是明文本身还是填充字符)。
修正方案
方案1:统一使用标准PKCS7填充(推荐)
修正后的Python代码
from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad from base64 import b64encode, b64decode plainData = 'SimpleTest123456' secretKey = '12345678901234567890123456789012' iv = b64decode(b'4HlDPfgsSe3eayaeNF4hpg==') # 使用PKCS7标准填充 plainDataPadded = pad(plainData.encode('utf-8'), AES.block_size) cipher = AES.new(bytes(secretKey, 'utf-8'), AES.MODE_CBC, iv) encryptedData = cipher.encrypt(plainDataPadded) print('Encrypted-Python: ', b64encode(encryptedData).decode('utf-8'))
修正后的PHP加密/解密代码
// PHP加密代码 $plainData = "SimpleTest123456"; $secretKey = "12345678901234567890123456789012"; $iv = base64_decode("4HlDPfgsSe3eayaeNF4hpg=="); $cipherType = "AES-256-CBC"; // OPENSSL_RAW_DATA输出原始二进制,默认使用PKCS7填充 $encryptedData = openssl_encrypt($plainData, $cipherType, $secretKey, OPENSSL_RAW_DATA, $iv); $encryptedData = base64_encode($encryptedData); echo "Encrypted-PHP: ".$encryptedData; // PHP解密代码 $encryptedData = base64_decode("替换为Python输出的加密字符串"); $plainText = openssl_decrypt($encryptedData, $cipherType, $secretKey, OPENSSL_RAW_DATA, $iv); echo "\n plainText:$plainText\n";
方案2:坚持使用零填充(不推荐,非标准)
修正后的Python代码(完善填充逻辑)
from Crypto.Cipher import AES from base64 import b64encode, b64decode plainData = 'SimpleTest123456' secretKey = '12345678901234567890123456789012' block_size = AES.block_size // 完善零填充:即使长度匹配块大小,也填充一个完整块 pad_len = block_size - len(plainData) % block_size plainDataPadded = plainData + pad_len * '\0' plainDataPadded = plainDataPadded.encode('utf-8') iv = b64decode(b'4HlDPfgsSe3eayaeNF4hpg==') cipher = AES.new(bytes(secretKey, 'utf-8'), AES.MODE_CBC, iv) encryptedData = cipher.encrypt(plainDataPadded) print('Encrypted-Python: ', b64encode(encryptedData).decode('utf-8'))
修正后的PHP代码(禁用自动填充)
// PHP加密代码 $plainData = "SimpleTest123456"; $secretKey = "12345678901234567890123456789012"; $blockSize = 16; // 手动零填充 $padLen = $blockSize - strlen($plainData) % $blockSize; $plainData .= str_repeat("\0", $padLen); $iv = base64_decode("4HlDPfgsSe3eayaeNF4hpg=="); $cipherType = "AES-256-CBC"; // 禁用PKCS7填充,使用OPENSSL_ZERO_PADDING $encryptedData = openssl_encrypt($plainData, $cipherType, $secretKey, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); $encryptedData = base64_encode($encryptedData); echo "Encrypted-PHP: ".$encryptedData; // PHP解密代码 $encryptedData = base64_decode("SdjLXWi+A7ZtCkReXnDU4g=="); $plainText = openssl_decrypt($encryptedData, $cipherType, $secretKey, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv); // 去除末尾的零填充字符 $plainText = rtrim($plainText, "\0"); echo "\n plainText:$plainText\n";
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

