You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:42:05