如何在Python中用Rijndael 256算法ECB模式实现同PHP一致的加密请求?
从PHP Rijndael 256 ECB加密迁移到Python的解决方案
首先得明确几个核心细节:PHP里的MCRYPT_RIJNDAEL_256指的是块大小为256位(32字节)的Rijndael算法,不是密钥长度;另外PHP的mcrypt_encrypt默认会用零填充把明文补足到块大小的整数倍,还有json_encode的输出格式要和Python的序列化结果严格一致,否则加密结果肯定对不上。
先看你的PHP实现:
$enc_request = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->_user_key, json_encode($request_params), MCRYPT_MODE_ECB));
再看你写的Python代码,问题主要出在填充处理、JSON序列化一致性,还有库的选择上——你用的rijndael库比较小众,推荐用更成熟的pycryptodome来实现,下面是完整的可运行方案:
步骤1:安装依赖
先安装pycryptodome(Python加密领域的主流维护库):
pip install pycryptodome
步骤2:完整Python实现代码
from Crypto.Cipher import AES import json import base64 def rijndael256_ecb_encrypt(key, plaintext): # 1. 对齐PHP的json_encode输出(默认无空格) json_str = json.dumps(plaintext, separators=(',', ':')) # 2. 零填充:补足到32字节(256位)的整数倍,和PHP mcrypt默认行为一致 block_size = 32 padding_length = block_size - len(json_str) % block_size padded_data = json_str + '\x00' * padding_length # 3. 初始化Rijndael-256(指定块大小32字节,对应PHP的MCRYPT_RIJNDAEL_256) cipher = AES.new(key.encode('utf-8'), AES.MODE_ECB, block_size=block_size) # 4. 加密后做Base64编码 encrypted_data = cipher.encrypt(padded_data.encode('utf-8')) return base64.b64encode(encrypted_data).decode('utf-8') # 测试示例 var = {'controller':'user','action':'check'} key = 'werewrewrewrwerlkewrjewklrwelkrwelkr' result = rijndael256_ecb_encrypt(key, var) print(result)
关键细节说明
- JSON序列化一致性:PHP的
json_encode默认不会生成空格,所以Python里必须用json.dumps(..., separators=(',', ':'))来匹配,哪怕是微小的空格差异都会导致加密结果完全不同。 - 零填充处理:PHP的
mcrypt_encrypt默认使用零填充,所以我们手动把明文填充到32字节的整数倍,不足的地方补\x00。 - Rijndael块大小设置:在
pycryptodome的AES类里,通过block_size=32来指定256位的块大小,这正好对应PHP的MCRYPT_RIJNDAEL_256。 - 编码统一:确保密钥、明文都统一为UTF-8编码,避免因编码不一致导致的加密差异。
如果坚持要用你原来的rijndael库,需要手动补全零填充逻辑并确认块大小参数传递正确,但还是推荐用pycryptodome——它维护更活跃、文档更完善,能减少踩坑概率。
内容的提问来源于stack exchange,提问作者Emipro Technologies Pvt. Ltd.
相关产品推荐
相关产品推荐

