ValueError: ключ AES должен иметь длину 16, 24 или 32 байта PyCrypto 2.7a1

python python-3.x cryptography pycrypto

6588 просмотра

1 ответ

Я делаю программу для своего школьного проекта, и у меня есть одна проблема выше. Вот мой код:

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

Что я делаю неправильно?

Автор: Tukanoid Источник Размещён: 08.11.2019 11:12

Ответы (1)


5 плюса

Решение

Ошибка очень понятна. Ключ должен быть именно такого размера. os.urandomвернет вам правильный ключ. Однако этот ключ является байтами (двоичное значение строки). Кроме того, используя str(secret), значение repr(secret)записывается в файл вместо secret.

Что еще более запутанно, так это то, что AES.newвы можете передать ключ как Unicode! Однако предположим, что ключом были байты ASCII 1234123412341234. В настоящее время,

f.write(str(secret))

напишу b'1234123412341234'в текстовый файл! Вместо 16 байтов теперь он содержит эти 16 байтов + символы кавычек bи два '; Всего 19 байтов.

Или если вы берете случайную двоичную строку из os.urandom,

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

теперь вместо записи 16 байтов D7, 82... и т. д. теперь эта строка записывается в файл. И ошибка возникает из-за того, что расшифровка пытается использовать

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

в качестве ключа дешифрования, который при кодировании как UTF-8 приводит к

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

это значение длиной 49 байтов bytes.


У вас есть 2 хороших выбора. Либо вы продолжаете записывать свой ключ в текстовый файл, но конвертируете его в шестнадцатеричный формат, либо записываете ключ в двоичный файл; тогда файл должен быть точно длиной ключа в байтах. Я собираюсь для последнего здесь:

Таким образом, для хранения ключа используйте

    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/decodeэто bytes-in / bytes-out.

Кстати, открытый текст - это оригинальный, незашифрованный текст; зашифрованный текст называется зашифрованным текстом . AES - это шифр, который может зашифровать открытый текст в зашифрованный текст и расшифровать зашифрованный текст в открытый текст с помощью ключа.

Несмотря на то, что они называются "-text", ни один из них не является текстовыми данными как таковыми, как это понимает Python, но они являются двоичными данными и должны быть представлены как bytes.

Автор: Antti Haapala Размещён: 20.08.2016 11:06
Вопросы из категории :
32x32