我想在Python中使用AES加密某些数据,以便对相同数据的两次加密提供相同的输出(在两次加密中使用相同的密钥)。我尝试使用静态IV但是在给定一个输入的情况下我仍然得到两个不同的输出。
这是我做的:
from Crypto.Cipher import AES
iv = 16 * '\x00'
cipher = AES.new(key, AES.MODE_CBC, iv)
如果我决定多次加密相同的数据,我想获得相同的密码。 你知道如何防止使用盐吗? 谢谢!
答案 0 :(得分:2)
这里的cipher
对象是状态,并使用提供的密钥数据和初始化向量进行初始化。一旦开始使用此初始化的密钥状态,就会对使用CBC模式时加密的每个块进行修改。这就是密码块的链接。要进行两次单独的加密,您需要使用两个单独的密钥状态。或者,如上所述,您可以使用在加密块时不影响keystate的模式(ECB)。
演示(python3):
from Crypto.Cipher import AES
key = 16 * b'\0'
iv = 16 * b'\0'
plaintext = 16 * b'\x41'
a = AES.new(key, AES.MODE_CBC, iv)
b = AES.new(key, AES.MODE_CBC, iv)
ar = a.encrypt(plaintext)
br = b.encrypt(plaintext)
>>> ar
b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
>>> br
b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
ECB模式的缺点是每次我们用这个密钥加密这个明文,我们就会得到这个结果。使用CBC模式,每次我们加密另一个块时,keystate都会被更改,我们会得到一个不同的输出,这取决于之前加密的内容。
ECB模式
>>> ecb = AES.new(16 * b'\0', AES.MODE_ECB)
>>> ecb.encrypt(16 * b'\x41')
b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
>>> ecb.encrypt(16 * b'\x41')
b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
每次加密都会产生相同的结果。不需要iv。
CBC模式
>>> cbc = AES.new(16 * b'\0', AES.MODE_CBC, 16 * b'\0')
>>> cbc.encrypt(16 * b'\x41')
b'\xb4\x9c\xbf\x19\xd3W\xe6\xe1\xf6\x84\\0\xfd[c\xe3'
>>> cbc.encrypt(16 * b'\x41')
b'o\x9fv\x9a\x9c\xaa\x03\x13\xba\x17\x8c\x1c.\x0f`v'
>>> cbc.encrypt(16 * b'\x41')
b'\n1\x165\xb5?\x04h\xa8\r>k\xdbK\xbc4'
第一个块加密与ECB模式相同,但后续块不同。
关于分组密码modes of operation的更多讨论可以在网上找到。