Расшифровка Python 256 AES с помощью pycryptodome

У меня есть устройство с последовательным портом TCP, которое получает данные через rs232, шифрует эти данные, а затем пересылает их на TCP-сервер. Документация по методологии шифрования устройства практически отсутствует, только 128-, 192- или 256-битное шифрование AES (настраивается). Судя по некоторым другим подсказкам контекста в документации, я вижу, что он, вероятно, использует режим работы CBC или CFB (хотя это также может быть неправильно). И нет, у меня нет понимания природы IV в документации. Возможно, это добавлено к зашифрованным данным?

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

Простой текст:

 b'\r\x00\nLocal: \r\x00\nACCESS            by user 5                                    22:49:32 03/07/11\r\x00\n'

Зашифровано:

b'$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9'

Ключ состоит из 64 шестнадцатеричных символов (очевидно, я изменю это): 566B59703373367638792F423F4528482B4D6251655468576D5A713474377721

Поэтому, когда я запускаю для него следующий код (пытаясь использовать как режим CFB, так и режим CBC), я не получаю ничего удобочитаемого.

from Crypto.Cipher import AES

encrypted_data = b"$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9"

key = bytes.fromhex("566B59703373367638792F423F4528482B4D6251655468576D5A713474377721")


def decrypt(data, key):

    print("Encrypted data: ", data)


    #trying CFB mode
    cipher = AES.new(key, AES.MODE_CFB)
    pt = cipher.decrypt(data)
    print("CFB mode outputs: ", pt)

    #now trying CBC mode
    #padding data per CBC requirements
    length = 16 - (len(data) % 16)
    data += bytes([length]) * length
    cipher = AES.new(key, AES.MODE_CBC)
    pt = cipher.decrypt(data)
    print("CBC mode outputs: ", pt)


decrypt(encrypted_data, key)

Выход:

Encrypted data:  b'$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9'
CFB mode output:  b'\xd3I\x95@[\xbeA\x15"W\xf4|\x7f\x93\x9d]\r\x10\xca\x9e\xc2\x9f\x8b\xfcDp :\x94\xdb\x85tS\xc4\xf4Lc\xe4\xa45\xa1{\x07\x0fOT\xbe\xe7u\x82\x8d\x01\x9a\x91A\xd6\x0f\x83\xe8\xf8\x80HP\x83 pu\xbaG\xae\xeb.\x9cTF\x17!\xa6\x0c) \xa8\xe7\x07\xf6J\'\xa7\xbc\x05\xcf\\\x7f\x1a.\xe83n\xe2<\xb7\xe51\xdcZ\\\x8b\xb2\xf2'
CBC mode output:  b'\x8d\x1f\xaf@\x8c\xab\xb7\xf5\x1a}\x05b@\xcf\xd7L\xaa\xcc\x1a6\x82\xd3)\xee\xc2\x03\xc7\xe6k\x04P+\x0b>\xc1\x9d\xf5S\x0c\x17\xaf\xf6\x1dV\xe2\xa4\x0e\x98[\xdd\xcd6\xb6\xde,\x8f\xdfS\xc2\xc3h\xc7x\xee\x10IFM\xb0\x11K\xd87\xec\x86\xc8\xac\xff\xdb\t\x19i9\xa1\xbe\xf5\x153\xfdv)\x8d\x0b\x1e\x0e\xa7I!vb\xe4\x87X6\x14\xb0\x87D\xdc\x10\x7f\x98'

Как заставить этот код выводить что-то удобочитаемое? Любые советы будут полезны! Благодарю вас!

-B


person Brenden Riggs    schedule 20.11.2020    source источник


Ответы (1)


CFB — это режим потокового шифрования, не требующий заполнения. Существуют различные варианты CFB, например. CFB1, CFB8, CFB128. CFB128 также часто называют CFB.

Числовое значение описывает количество битов открытого текста, зашифрованных за один шаг шифрования.

Отправленный зашифрованный текст может быть успешно расшифрован с помощью CFB128.

В PyCryptodome числовое значение указывается параметром segment_size, здесь

Кроме того, зашифрованные данные содержат 16 байт IV, размещенных впереди (как вы уже предположили), так что IV и фактический зашифрованный текст должны быть разделены в первую очередь.

Следующий код расшифровывает зашифрованный текст:

from Crypto.Cipher import AES

encrypted_data = b"$+\xf5Sq\x1aBC\xbe\t\x8f2\x0b\xf9\xdc!\x80By2\xbb\x10k\x03G\xbb\x85\xd5u\x1dM\xeb\xfd\xa8\xf4\xa13GX|\x06\x0e\xa7K\x0f\xbc\xca\x82js)Q\xff\xbc\xbd\xe2\x05mfJ\xe7g\xdc\xd3b\xff_O\xaeNDH\xb4\x8e\xb7\xbf$2\xba\xe6\xd1\x1bu\n\xe2\x05\xae\x1a\xfc\xd7v\x06\xe6/^&v\xd4\x1a-\x0f\x16o\xc7\xeb\xc4\x90h\xe9"

key = bytes.fromhex("566B59703373367638792F423F4528482B4D6251655468576D5A713474377721")

def decrypt(data, key):

    #print("Encrypted data: ", data)

    iv = data[:16]                                             # Separate IV
    ciphertext = data[16:]                                     # and actual ciphertext

    #trying CFB mode
    cipher = AES.new(key, AES.MODE_CFB,iv=iv,segment_size=128) # Specify CFB128
    pt = cipher.decrypt(ciphertext)
    print("CFB mode outputs: ", pt) 

decrypt(encrypted_data, key)

с выводом:

CFB mode outputs:  b'\r\nLocal: \r\nACCESS            by user 5                                    22:49:32 03/07/11\r\n'
person user 9014097    schedule 20.11.2020