以下代码每次执行时都会生成不同的ciphertext
,这不应该发生,因为每次执行时传递的密钥和数据都是相同的。
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from base64 import b64encode, b64decode
key = '/I02fMuSSvnouuu+/vyyD7NuSEVDB/0gte/z50dM0b4='
data = 'hello world!'
cipher = AES.new(b64decode(key), AES.MODE_CBC)
padded_data = pad(data.encode(), cipher.block_size)
print(b64encode(padded_data))
# b'aGVsbG8gd29ybGQhBAQEBA=='
ciphertext = cipher.encrypt(padded_data)
print(b64encode(ciphertext))
# b'rEHH0MWIWCWUldjYBco9TA=='
ciphertext = cipher.encrypt(padded_data)
print(b64encode(ciphertext))
# b'FTpLrkZttDxMlpre3Kq8qQ=='
我实际上是在尝试将示例PHP代码复制到Python,PHP代码提供相同的输出,我的Python代码提供不同的输出,其中没有一个匹配PHP。
Python版本3.6.x PyCryptoDome版本3.4.7
每次使用Pycryptodome在CBC模式下生成AES密码对象时,都会创建并使用随机IV。它可以作为名为iv
的属性访问(例如cipher.iv
)。
独特(且不可预测)的IV实现了随机化输出的目标,即使相同的消息被多次加密(使用相同的密钥),这是攻击者经常可以利用的一条信息。
您不显示PHP代码,但如果其输出不会每次都更改,则意味着IV已修复且代码存在安全漏洞。
我忘了在创建iv
parameter对象时传递cipher
。
应该是这样的 -
cipher = AES.new(b64decode(key), AES.MODE_CBC, iv=b'0123456789abcdef')
是的,正确的pointed out by Rawing,重复使用相同的cipher
对象加密将给出不同的结果,但如果你重建cipher
对象,它将始终给出相同的输出。
cipher = AES.new(b64decode(key), AES.MODE_CBC, iv=b'0123456789abcdef')
padded_data = pad(data.encode(), cipher.block_size)
print(b64encode(padded_data))
# b'aGVsbG8gd29ybGQhBAQEBA=='
ciphertext = cipher.encrypt(padded_data)
print(b64encode(ciphertext))
# b'8G0KL2UiCv7Uo+pKMm9G+A=='
ciphertext = cipher.encrypt(padded_data)
print(b64encode(ciphertext))
# b'tBXcf/Nf6MtxM1ulzNnIlw=='
cipher = AES.new(b64decode(key), AES.MODE_CBC, iv=b'0123456789abcdef')
padded_data = pad(data.encode(), cipher.block_size)
ciphertext = cipher.encrypt(padded_data)
print(b64encode(ciphertext))
# b'8G0KL2UiCv7Uo+pKMm9G+A=='