PyCrypto - 初始化向量如何工作?

Tim*_*all 12 python pycrypto initialization-vector python-3.x

我试图了解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()
Run Code Online (Sandbox Code Playgroud)

我正在使用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."

Squ*_*ree 19

您看到的行为特定于CBC模式.使用CBC,可以通过以下方式(来自维基百科)可视化解密:

CBC解密

您可以看到IV仅对明文的前16个字节有贡献.如果IV在传输到接收器时被破坏,CBC仍将正确解密除第一个块之外的所有块.在CBC中,IV的目的是使您能够使用相同的密钥加密相同的消息,并且每次仍然获得完全不同的密文(即使消息长度可能会给出一些东西).

其他模式不太宽容.如果您的IV出错,整个消息在解密时会出现乱码.以CTR模式为例,其中nonceIV的含义几乎相同:

点击率模式