我正在尝试理解PyCrypto如何在项目中使用,但我还没有完全理解初始化向量(IV)的重要性。我发现在解码字符串时我可以使用错误的IV,除了前16个字节(块大小)之外我似乎仍然收到消息。我只是错误地使用它或不理解某些东西?
以下是示例代码:
import Crypto
import Crypto.Random
from Crypto.Cipher import AES
def pad_data(data):
if len(data) % 16 == 0:
return data
databytes = bytearray(data)
padding_required = 15 - (len(databytes) % 16)
databytes.extend(b'\x80')
databytes.extend(b'\x00' * padding_required)
return bytes(databytes)
def unpad_data(data):
if not data:
return data
data = data.rstrip(b'\x00')
if data[-1] == 128: # b'\x80'[0]:
return data[:-1]
else:
return data
def generate_aes_key():
rnd = Crypto.Random.OSRNG.posix.new().read(AES.block_size)
return rnd
def encrypt(key, iv, data):
aes = AES.new(key, AES.MODE_CBC, iv)
data = pad_data(data)
return aes.encrypt(data)
def decrypt(key, iv, data):
aes = AES.new(key, AES.MODE_CBC, iv)
data = aes.decrypt(data)
return unpad_data(data)
def test_crypto ():
key = generate_aes_key()
iv = generate_aes_key() # get some random value for IV
msg = b"This is some super secret message. Please don't tell anyone about it or I'll have to shoot you."
code = encrypt(key, iv, msg)
iv = generate_aes_key() # change the IV to something random
decoded = decrypt(key, iv, code)
print(decoded)
if __name__ == '__main__':
test_crypto()
我正在使用Python 3.3。
输出会因执行而异,但我会得到类似的结果:b"1^,Kp}Vl\x85\x8426M\xd2b\x1aer secret message. Please don't tell anyone about it or I'll have to shoot you."
答案 0 :(得分:19)
您看到的行为特定于CBC模式。使用CBC,可以通过以下方式(来自维基百科)可视化解密:
您可以看到IV仅对明文的前16个字节有贡献。如果IV在传输到接收器时被破坏,CBC仍将正确解密除第一个块之外的所有块。在CBC中,IV的目的是使您能够使用相同的密钥加密相同的消息,并且每次仍然获得完全不同的密文(即使消息长度可能会给出一些东西)。
其他模式不太宽容。如果您的IV出错,整个消息在解密时会出现乱码。以CTR模式为例,其中 nonce 与 IV 具有几乎相同的含义:
答案 1 :(得分:1)
PyCrypto的开发人员从NIST取消了AES CBC Mode的规范:
AES Mode_CBC - >引用NIST 800-38a (The Recommendation for Cipher Mode Operations)
从那,第8页:
5.3初始化向量
除了明文之外,CBC,CFB和OFB模式的加密过程的输入还包括称为初始化矢量(IV)的数据块,表示为IV。 IV用于加密消息和消息的相应解密的初始步骤。 IV不必是秘密的;然而,对于CBC和CFB模式,IV适用于任何特定的 加密过程的执行必须是不可预测的,并且对于OFB模式,每次执行加密过程都必须使用唯一的IV 。 IV的产生在附录C中讨论。
要记住,每次撰写邮件时都需要使用随机IV,这会在邮件中添加“盐”,从而使邮件独一无二;即使“盐”在外面打开,如果AES加密密钥未知,也无法破解加密。如果您不使用随机IV,比如说,每个消息都使用相同的16个字节,那么如果您重复自己的消息,那么您的消息看起来会相同,并且可能会受到频率和/或重放攻击。< / p>
随机IVs与静态结果的测试:
def test_crypto ():
print("Same IVs same key:")
key = generate_aes_key()
iv = b"1234567890123456"
msg = b"This is some super secret message. Please don't tell anyone about it or I'll have to shoot you."
code = encrypt(key, iv, msg)
print(code.encode('hex'))
decoded = decrypt(key, iv, code)
print(decoded)
code = encrypt(key, iv, msg)
print(code.encode('hex'))
decoded = decrypt(key, iv, code)
print(decoded)
print("Different IVs same key:")
iv = generate_aes_key()
code = encrypt(key, iv, msg)
print(code.encode('hex'))
decoded = decrypt(key, iv, code)
print(decoded)
iv = generate_aes_key()
code = encrypt(key, iv, msg)
print(code.encode('hex'))
decoded = decrypt(key, iv, code)
print(decoded)
希望这有帮助!