python - ValueError : AES key must be either 16, 24 或 32 字节长 PyCrypto 2.7a1

标签 python python-3.x cryptography pycrypto

我正在为我的学校项目编写程序并遇到上述问题。 这是我的代码:

def aes():
    #aes
    os.system('cls')
    print('1. Encrypt')
    print('2. Decrypt')

    c = input('Your choice:')

    if int(c) == 1:
        #cipher
        os.system('cls')
        print("Let's encrypt, alright")
        print('Input a text to be encrypted')
        text = input()

        f = open('plaintext.txt', 'w')
        f.write(text)
        f.close()

        BLOCK_SIZE = 32
        PADDING = '{'
        pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
        EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
        secret = os.urandom(BLOCK_SIZE)

        f = open('aeskey.txt', 'w')
        f.write(str(secret))
        f.close()

        f = open('plaintext.txt', 'r')
        privateInfo = f.read()
        f.close()

        cipher = AES.new(secret)

        encoded = EncodeAES(cipher, privateInfo)

        f = open('plaintext.txt', 'w')
        f.write(str(encoded))
        f.close()
        print(str(encoded))

    if int(c) == 2:
        os.system('cls')
        print("Let's decrypt, alright")

        f = open('plaintext.txt','r')
        encryptedString = f.read()
        f.close()

        PADDING = '{'
        DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
        encryption = encryptedString

        f = open('aeskey.txt', 'r')
        key = f.read()
        f.close()

        cipher = AES.new(key)
        decoded = DecodeAES(cipher, encryption)

        f = open('plaintext.txt', 'w')
        f.write(decoded)
        f.close()

        print(decoded)

完整的错误文本:

Traceback (most recent call last): File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 341, in aes() 
File "C:/Users/vital/Desktop/Prog/Python/Enc_dec/Enc_dec.py", line 180, in aes cipher = AES.new(key) 
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 179, in new return AESCipher(key, *args, **kwargs) 
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\AES.py", line 114, in init blockalgo.BlockAlgo.init(self, _AES, key, *args, **kwargs) 
File "C:\Users\vital\AppData\Local\Programs\Python\Python35-32\lib\site-packages\Crypto\Cipher\blockalgo.py", line 401, in init self._cipher = factory.new(key, *args, **kwargs)
ValueError: AES key must be either 16, 24, or 32 bytes long

Process finished with exit code 1

我做错了什么?

最佳答案

错误很明显。 key 必须恰好是该大小。 os.urandom 将返回正确的 key 。然而这个键是一个bytes(二进制字符串值)。此外,通过使用 str(secret)repr(secret) 的值被写入文件而不是 secret

更令人困惑的是 AES.new 允许您将 key 作为 Unicode 传递!但是,假设 key 是 ASCII 字节 1234123412341234。现在,

f.write(str(secret))

b'1234123412341234' 写入文本文件!它现在包含这 16 个字节 + b 和两个 ' 引号字符,而不是 16 个字节;共19个字节。

或者,如果您从 os.urandom 中获取一个随机二进制字符串,

>>> os.urandom(16)
b'\xd7\x82K^\x7fe[\x9e\x96\xcb9\xbf\xa0\xd9s\xcb'

现在,它不再写入 16 个字节 D782 等等,而是将该字符串写入文件。并且发生错误是因为解密尝试使用

"b'\\xd7\\x82K^\\x7fe[\\x9e\\x96\\xcb9\\xbf\\xa0\\xd9s\\xcb'"

作为解密 key ,当编码为 UTF-8 时会产生

b"b'\\xd7\\x82K^\\x7fe[\\x9e\\x96\\xcb9\\xbf\\xa0\\xd9s\\xcb'"

这是一个 49 字节长的 bytes 值。


您有 2 个不错的选择。要么继续将 key 写入文本文件,但将其转换为十六进制,要么将 key 写入二进制文件;那么文件应该正好是 key 长度(以字节为单位)。我在这里选择后者:

因此为了存储 key ,使用

    with open('aeskey.bin', 'wb') as keyfile:
        keyfile.write(secret)

    with open('aeskey.bin', 'rb') as keyfile:
        key = keyfile.read()

同样自然地适用于密文(即加密的二进制文件),您必须将其写入二进制文件并从中读取:

    with open('ciphertext.bin', 'wb') as f:
        f.write(encoded)

    with open('ciphertext.bin', 'rb') as f:
        encryptedString = f.read()

如果您想对其进行 base64 编码,请注意 base64.b64encode/decodebytes-in/bytes-out。

顺便说一下,plaintext是原始的、未加密的文本;加密文本称为 ciphertext . AES 是一种密码,可以使用 key 将明文加密为密文,并将密文解密为明文。

尽管它们被称为“-text”,但它们本身都不是 Python 所理解的文本数据,而是二进制数据,应该表示为 bytes

关于python - ValueError : AES key must be either 16, 24 或 32 字节长 PyCrypto 2.7a1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39053286/

相关文章:

ios - Swift 4.0 的 CryptoSwift Lib 安装失败

python - 验证 HTTP 请求的来源

python - 如何在 Python 中解析 RSS feed 中的 HTML 标签

python - 如何避免 matplotlib 中多条形图中条形之间的重叠

python - Python 中绝对差的均值

python - 如何存储 TfidfVectorizer 以备将来在 scikit-learn 中使用?

java - 尝试比较我的两个哈希值。两者都是大整数形式

python - 通过 Google Cloud Speech API 获取每个转录单词的时间戳?

python - 字典操作顺序

python - 如何在 Django ORM 查询中进行日期数学运算?