5

我正在使用 PyCrypto 在 CBC 模式下使用 AES 加密二进制文件(Python 3.2.3 64 位和 PyCrypto 2.6)。使用以下代码:http ://eli.thegreenplace.net/2010/06/25/aes-encryption-of-files-in-python-with-pycrypto/

但遇到以下错误:ValueError: IV must be 16 bytes long。

这是代码:

def encryptFile(key, in_filename, out_filename=None, chunksize=64*1024):
""" Encrypts a file using AES (CBC mode) with the
    given key.

    key:
        The encryption key - a string that must be
        either 16, 24 or 32 bytes long. Longer keys
        are more secure.

    in_file:
        Input file

    out_file:
        If None, a StringIO will be returned.

    chunksize:
        Sets the size of the chunk which the function
        uses to read and encrypt the file. Larger chunk
        sizes can be faster for some files and machines.
        chunksize must be divisible by 16.
"""
if not out_filename:
    out_filename = in_filename + '.enc'

iv = ''.join(chr(random.randint(0, 0xFF)) for i in range(16))
encryptor = AES.new(key, AES.MODE_CBC, iv)
filesize = os.path.getsize(in_filename)

with open(in_filename, 'rb') as infile:
    with open(out_filename, 'wb') as outfile:
        outfile.write(struct.pack('<Q', filesize))
        outfile.write(iv)

        while True:
            chunk = infile.read(chunksize)
            if len(chunk) == 0:
                break
            elif len(chunk) % 16 != 0:
                chunk += ' ' * (16 - len(chunk) % 16)

            outfile.write(encryptor.encrypt(chunk))

我已经尝试过搜索和试验,但似乎无法让它发挥作用。Python 对我来说很新,加密也是。任何帮助将不胜感激。提前致谢。

4

2 回答 2

7

正如 PyCrypto API 所说,IV必须是字节字符串,而不是文本字符串。

您的代码在 Python 2 中可以正常工作,因为它们是相同的(也就是说,它们都是 class str,除非您处理 Unicode 文本)。在 Python 3 中,它们是两种完全不同的类型:bytesstr.

因此,代码应为:

iv = bytes([ random.randint(0,0xFF) for i in range(16)] )

不过,这样的代码(除了 Federico 指出的那样不具有密码安全性)在 Python 2 中将无法正常工作。以下替代方案在这两种情况下都可以正常工作,它安全且更有效:

iv = Random.new().read(16)
于 2012-06-09T08:59:48.257 回答
2

我想我为时已晚,但是simple-crypt提供了一个简单的 pycrypto 包装器,它(1)可以解决您的问题,(2)包括密钥扩展和用于检测修改的 hmac(它使用 AES256 CTR 模式)。

于 2013-02-02T14:00:43.410 回答