ValueError: проверка MAC не удалась при использовании PyCryptodome для расшифровки данных, поступающих от NiFi

Может ли кто-нибудь помочь мне с этой проблемой:

Я шифрую JSON в NiFi с помощью алгоритма AES_GCM и использую KDF PBKDF2. Идея состоит в том, чтобы расшифровать этот JSON с помощью скрипта Python, используя PyCryptodome.

Следующий код — это попытка увидеть, можно ли расшифровать зашифрованное сообщение NiFi:

import base64
from Crypto.Protocol.KDF import PBKDF2
from Crypto.Cipher import AES

# Key used in NiFi to encrypt the JSON
key = '-JaNcRfUjXn2r5u8'

# Result value after the EncryptContent processor encrypts 
# the JSON: {"id":"123", "name":"Ronald"}
value = 'nTJuV9l9uQJrWv2HXD37PE5pRmlTQUxUg7ir0oDxuxSnmuqZpbUfVk5pRmlJVn1yT10SdXKjobe9o/QHybJqwhPgCifGz2yiY9JICGehICb/zEsYUivERcMKhg=='

decodeValue = base64.b64decode(value)

salt = decodeValue[:16]
IV = decodeValue[24:40]
dataToDecrypt = decodeValue[46:-16]
tag = decodeValue[-16:]

mainKey = PBKDF2(key, salt)

cipher = AES.new(mainKey, AES.MODE_GCM, IV)
cipher.update(salt)

decryptedData = cipher.decrypt_and_verify(dataToDecrypt, tag)

print(decryptedData)

Я понимаю, что в NiFi с шифрованием NIFI_PBKDF2_AES_GCM_128 вывод зашифрованного текста состоит из соли (длиной 16 байт), за которой следует разделитель соли, строка UTF-8 «NiFiSALT» (0x4E 69 46 69 53 41 4C 54), а затем IV , за которым следует разделитель IV, строка UTF-8 «NiFiIV» (0x4E 69 46 69 49 56), за которой следует зашифрованный текст, за которым следует тег аутентификации (длиной 16 байт), но при попытке запустить приведенный выше скрипт с помощью этой структуры, я получаю следующую ошибку:

Traceback (most recent call last):
  File "/home/ronald/anaconda3/envs/Quind/lib/python3.10/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 4, in <module>
  File "/home/ronald/anaconda3/envs/Quind/lib/python3.10/site-packages/Crypto/Cipher/_mode_gcm.py", line 567, in decrypt_and_verify
    self.verify(received_mac_tag)
  File "/home/ronald/anaconda3/envs/Quind/lib/python3.10/site-packages/Crypto/Cipher/_mode_gcm.py", line 508, in verify
    raise ValueError("MAC check failed")
ValueError: MAC check failed

Я не понимаю, почему проверка тега аутентификации не удалась.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Расшифровка не работает по двум причинам:

  • Для PBKDF2 ни количество итераций, ни дайджест явно не указаны, поэтому используются значения по умолчанию 1000 и SHA1. Однако применяемые значения — 160000 и SHA512 в соответствии с документацией :

    from Crypto.Hash import SHA512
    ...
    mainKey = PBKDF2(key, salt, count=160000, hmac_hash_module=SHA512)
    
  • Соль не аутентифицируется, т.е. строку cipher.update(salt) нужно убрать.

С этими изменениями аутентификация и дешифрование проходят успешно, и decryptedData становится b'{"id": "123", "name": "Ronald"}'.


Обратите внимание, что для GCM допускается длина 16 байтов для nonce/IV, но рекомендуемая длина составляет 12 байтов. Но, возможно, изменение находится вне вашего контроля.

Другие вопросы по теме