.NET 4.2.7 AES-256加密结果与Python不符,求问题排查方案
AES-256加密:.NET与Python实现结果不一致问题排查
问题背景
客户提供基于.NET 4.2.7的C# AES-256加密代码作为规范,用Python 2.7实现对应逻辑后,加密结果无法匹配。为排查问题,将明文、密钥、IV均设置为全零值,得到两组不同输出。
C#(.NET 4.2.7)代码及输出
private static void TestEncrypt2() { byte[] bytesToEncrypt = new byte[] { 0x00, 0x00, 0x00, 0x00 }; byte[] encrypted = null; using (var cryptoService = Aes.Create()) { cryptoService.Key = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; cryptoService.IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; using (ICryptoTransform encryptor = cryptoService.CreateEncryptor(cryptoService.Key, cryptoService.IV)) { using (MemoryStream msEncrypt = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { csEncrypt.Write(bytesToEncrypt, 0, bytesToEncrypt.Length); csEncrypt.FlushFinalBlock(); encrypted = msEncrypt.ToArray(); } } } } DumpByteArray(encrypted); }
输出:
Test Encrypt 2, zero data, key and IV:
B5 67 D8 36 7C FD F3 7A
89 8F 18 3A 49 83 7A D3
Python 2.7代码及输出
from Crypto.Cipher import AES import struct def ByteListToPackedString(byte_list): return ''.join(chr(b) for b in byte_list) def HexStringToByteList(hex_str): return [int(hex_str[i:i+2], 16) for i in range(0, len(hex_str), 2)] def PackedStringToHexString(packed_str): return ''.join('%02X' % ord(c) for c in packed_str) def SREncrypt0(): packedIv = ByteListToPackedString([0]*16) packedKey = ByteListToPackedString([0]*32) c = AES.new(packedKey, AES.MODE_CBC, packedIv) packedClr = ByteListToPackedString(HexStringToByteList("00000000")) while 0 != (len(packedClr) % 16): packedClr += struct.pack("B", 0) # 补零填充 return PackedStringToHexString(c.encrypt(packedClr)) # 输出结果:DC95C078A2408989AD48A21492842087
输出:
DC95C078A2408989AD48A21492842087
Python结果与标准加密工具输出一致。
问题原因及解决方案
1. 核心原因:填充模式不匹配
.NET的Aes类默认使用PKCS#7填充,而你的Python代码采用补零填充,这是导致结果差异的根本原因:
- 对于4字节明文,PKCS#7会填充12个
0x0C(填充字节的值等于填充长度); - 补零填充则填充12个
0x00。
2. 统一填充模式的两种方案
方案一:修改Python代码使用PKCS#7填充
from Crypto.Cipher import AES from Crypto.Util.Padding import pad def ByteListToPackedString(byte_list): return ''.join(chr(b) for b in byte_list) def HexStringToByteList(hex_str): return [int(hex_str[i:i+2], 16) for i in range(0, len(hex_str), 2)] def PackedStringToHexString(packed_str): return ''.join('%02X' % ord(c) for c in packed_str) def SREncrypt0(): packedIv = ByteListToPackedString([0]*16) packedKey = ByteListToPackedString([0]*32) c = AES.new(packedKey, AES.MODE_CBC, packedIv) packedClr = ByteListToPackedString(HexStringToByteList("00000000")) # 替换为PKCS#7填充 padded_clr = pad(packedClr, AES.block_size, style='pkcs7') return PackedStringToHexString(c.encrypt(padded_clr)) # 输出将与C#结果一致:B567D8367CFDF37A898F183A49837AD3
方案二:修改C#代码使用补零填充
在C#代码中添加一行设置填充模式:
cryptoService.Padding = PaddingMode.Zeros;
修改后C#代码的输出将和Python补零填充的结果完全匹配。
3. 关于.NET版本与BouncyCastle
不需要升级.NET版本,也不需要引入BouncyCastle库。问题并非.NET的AES实现存在缺陷,仅为填充模式的配置差异。
内容的提问来源于stack exchange,提问作者Larry Martin
相关产品推荐
相关产品推荐

