Несоответствие pycryprodome AES CBC после расшифровки в Python

моя цель состоит в том, чтобы иметь очень простую схему AES 128 CBC, которая шифрует открытый текст, а затем расшифровывает его на основе заданного ключа в Python. Я использую pycryptodome framework и не смог найти никакой документации с примером схемы AES CBC.

Ниже приведен мой код. Расшифрованные данные отличаются от данных до шифрования. Будет здорово, если кто-нибудь поможет мне определить, что здесь происходит не так.

key = b'Sixteen byte key'
data = 'Jeevan B Manoj'.encode("UTF-8")
data = pad(data,16)
cipher = AES.new(key, AES.MODE_CBC)
print("data before encryption")
print(data)
ciphertext = cipher.encrypt(data)
cipher = AES.new(key, AES.MODE_CBC)
plaintext = cipher.decrypt(ciphertext)
print(plaintext)

person Jeevan_MSFT_Identity    schedule 11.04.2018    source источник
comment
Вам придется использовать капельницу. Если IV не передается AES.new, он создает случайный IV.   -  person t.m.adam    schedule 11.04.2018


Ответы (2)


Как заметил tmadam, режим работы CBC для работы требуется вектор инициализации (IV). Поскольку IV обычно забывают (а также то, что он должен быть уникальным и непредсказуемым, например, случайным), Pycryptodome создает случайный при инициализации объекта шифрования.

IV должен быть уникальным для каждого шифрования и требуется для расшифровки. Обычная практика (источник?) - помещать IV в начало зашифрованного текста (IV не обязательно должен быть секретным).

Чтобы ваш пример работал:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

# Do not use raw passwords as keys,
# use a derivation functions to generate keys from them
key = b'Sixteen byte key'  
data = 'Jeevan B Manoj'.encode("UTF-8")
data = pad(data, AES.block_size)
encryptor = AES.new(key, AES.MODE_CBC)
iv = encryptor.IV
decryptor = AES.new(key, AES.MODE_CBC, IV=iv)

ciphertext = encryptor.encrypt(data)
plaintext = decryptor.decrypt(ciphertext)

assert plaintext == data

Важное примечание. Зашифрованный текст и IV должны быть аутентифицированы в целях безопасности (чтобы данные нельзя было подделать). Для этого Pycryptodome предлагает режимы AEAD, такие как EAX и GCM, как указано Hans-Peter. Янсен на GitHub. Для многих из них прокладка не требуется.

person S. Biewald    schedule 15.04.2018

Если вы используете MODE_ECB вместо MODE_CBC, это работает. Я также не знал, какую процедуру заполнения вы используете, поэтому я использовал эту. У меня есть несколько других примеров: https://github.com/SolarDon/pycryptodome/tree/master/Examples

from Crypto.Cipher import AES
 # Padding for the input string --not related to encryption itself.
BLOCK_SIZE = 16  # Bytes
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

key = b'Sixteen byte key'
data = 'Jeevan B Manoj'.encode("UTF-8")
data = pad(data)
cipher = AES.new(key, AES.MODE_ECB) # AES.MODE_CBC
print("data before encryption")
print(data)
ciphertext = cipher.encrypt(data)
cipher = AES.new(key, AES.MODE_ECB) # MODE_CBC
plaintext = cipher.decrypt(ciphertext)
print(unpad(plaintext))
person Donald Wagner    schedule 12.04.2018
comment
crypto.stackexchange.com/questions/ 20941/ - person Ilmari Karonen; 12.04.2018