Python AES 实现的区别

5 投票
3 回答
1145 浏览
提问于 2025-04-18 06:31

我正在比较Python中两个库的AES实现,一个是pycrypto,另一个是cryptography.io

from cryptography.hazmat.primitives.ciphers import Cipher, modes, algorithms
from cryptography.hazmat.backends import default_backend  # http://cryptography.io
from Crypto.Cipher import AES  # http://pycrypto.org

key = b'Sixteen byte key'
iv = b'Sixteen byte ivv'
cipher1 = AES.new(key, AES.MODE_CFB, iv)
cipher2 = Cipher(algorithms.AES(key), modes.CFB(iv), default_backend())

plaintext = b"Plaintext"

print(cipher1.encrypt(plaintext))
print(cipher1.decrypt(plaintext))
print(cipher2.encryptor().update(plaintext))
print(cipher2.decryptor().update(plaintext))

这个最小可重现示例的输出是:

b'\xe4\xb4\xeb\xe3Si\x9ap\xee'
b'7\xda\x98\xee\x05\xe4\xa0\xc7,'
b'\xe4"\xd4mo\xa3;\xa9\xe0'
b'\xe4"\xd4mo\xa3;\xa9\xe0'

为什么输出结果会不一样呢?

3 个回答

0

请使用加密模式“CFB8”。这样,pycrypto和cryptography的输出结果会一致。比如,你可以这样写:cipher2 = Cipher(algorithms.AES(key), modes.CFB8(iv), default_backend())

2

根据Alex Gaynor的回答,这里有一个更详细的说明:

根据标准,输入的数据大小必须是段大小的整数倍。大多数实现默认使用16字节(128位)的段大小,并且忽略了这个要求。PyCrypto默认使用8字节的段,但你可以这样更改:

cipher1 = AES.new(key, AES.MODE_CFB, iv, segment_size=128)

这样做会产生与其他库相同的加密数据。

4

这个回答的意思是,PyCrypto 默认使用的是 CFB-8,这是一种普通 CFB 的变种。详细的问题描述可以在这个链接找到:https://github.com/digitalbazaar/forge/issues/100

撰写回答