Байты в строку в AES-шифровании и дешифровании в Python 3 - PullRequest
0 голосов
/ 23 мая 2018

Я хочу сделать шифрование AES и расшифровку строки.но ключ и сообщение должны быть в байтах, поэтому я преобразовал сообщение в байты следующим образом:

b"string"

Это мой код AES:

# Encryption
encryption_suite = AES.new(b'1234567812345678', AES.MODE_OCB)
cipher_text = encryption_suite.encrypt(b"A really secret message. Not for prying eyes.")

# Decryption
decryption_suite = AES.new(b'1234567812345678', AES.MODE_OCB)
plaintext = decryption_suite.decrypt(cipher_text)

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

b'x \ x85 \ x92 \ x9d \ xe6 \ x0bJ \ xfe \ x9b (\ x10G \ x8e \ x05 \ xc5 \ xf4 \ xcdA9 \ xc18 \ xb8_ \ xf9vbmK \x16 \ xf8 \ xa3 \ xb6 '

Я пытался использовать

plaintext.decode(encoding='windows-1252')

и

plaintext.decode("utf-8").strip('\x00')

, но все, что я получаю, это:

UnicodeDecodeError: кодек 'charmap' не может декодировать байт 0x9d в позиции 3: символ отображается на

или это:

UnicodeDecodeError: кодек 'utf-8' не может декодировать байт 0xb1 в позиции 1: неверный начальный байт

Мне нужно преобразовать эти байты обратно в читаемую строку ... если вы можете помочь, это будет оценено.

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

Основная проблема с вашим кодом заключается в том, что вы не указали одноразовый номер для AES.new().OCB требует одноразового номера;если вы не предоставите один, случайный одноразовый номер будет создаваться каждый раз, когда вы создаете новый объект AES, и поэтому расшифровка не удастся.

Из документов :

nonce (строка байтов): неповторяемое значение длиной от 1 до 15 байтов. Если нетВ настоящее время будет создан случайный одноразовый номер рекомендуемой длины (15 байт).

У вас есть два варианта: либо создать одноразовый номер и передать его в AES.new() (при шифровании и дешифровании), либо использовать случайный одноразовый номер, созданный AES во время шифрования.

Далее, OCB - это аутентифицированный алгоритм шифрования, но, похоже, вы не проверяете MAC.Это важно, потому что MAC проверяет целостность зашифрованного текста.

Методы шифрования и дешифрования AES принимают и возвращают байты.Вы можете преобразовать открытый текст (если это текст) в строку с .decode().Если вы хотите преобразовать зашифрованный текст в строку, вам придется сначала кодировать его base64, чтобы кодировать необработанные байты в символы ASCII (просто не забудьте декодировать перед расшифровкой).b64encode() также возвращает байты, но может быть легко преобразован в строку.

Например,

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
from base64 import b64encode

key = get_random_bytes(16) # A 16 byte key for AES-128
nonce = get_random_bytes(15)
message = "A really secret message. Not for prying eyes.".encode()

cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
ciphertext, mac = cipher.encrypt_and_digest(message)

cipher = AES.new(key, AES.MODE_OCB, nonce=nonce)
plaintext = cipher.decrypt_and_verify(ciphertext, mac)

print(b64encode(ciphertext).decode())
#CSwHy3ir3MZ7yvZ4CzHbgYOsKgzhMqjq6wEuutU7vJJTJ0c38ExWkAY1QkLO
print(plaintext.decode())
#A really secret message. Not for prying eyes.

Обратите внимание, что если .decrypt_and_verify() не удается проверить MAC, исключение ValueError будетподнят, так что вы можете использовать блок try-Кроме.Значения nonce и mac не являются секретными, и их безопасно хранить рядом с зашифрованным текстом.

Наконец, если вы планируете получить ключ из ключевой фразы, вам следует использовать KDF на основе пароля.KDF создают сильные ключи, используют соли и итерации, и они очень устойчивы к атакам с применением силы.Функции KDF вы найдете в Crypto.Protocol.KDF.

0 голосов
/ 26 июня 2019

Я думаю, что ваша кодировка "ISO-8859-1".Так что вы можете сделать:

plaintext.decode("ISO-8859-1")
0 голосов
/ 23 мая 2018

Нельзя преобразовать двоичные данные в строку, поскольку они по своей природе не строка.Это двоичные данные.Шансы на то, что результат вашего шифрования, случайно, окажется случайно отформатированной строкой UTF8, весьма маловероятны.

Вместо этого вам следует взглянуть на base64.Он раздувает данные (от 3 байтов до 4 символов), но лучше подходит для вашего варианта использования.

РЕДАКТИРОВАТЬ:Моя ошибка, я неправильно понял ваш вопрос.Вывод у вас неправильный, первый байт не равен «1» в UTF8.Это, вероятно, проблема с шифрованием / дешифрованием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...