Can someone help me with this problem:
I am encrypting a JSON in NiFi with AES_GCM algorithm and using a KDF PBKDF2. The idea is to decrypt this JSON with a python script using PyCryptodome.
The following code is an attempt to see if the NiFi encrypted message can be decrypted:
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)
I understand that in NiFi with NIFI_PBKDF2_AES_GCM_128 encryption the cipher text output consists of the salt (16-byte length), followed by the salt delimiter, UTF-8 string “NiFiSALT” (0x4E 69 46 69 53 41 4C 54) and then the IV, followed by the IV delimiter, UTF-8 string “NiFiIV” (0x4E 69 46 69 49 56), followed by the cipher text, followed by the autehnticaion tag (16-byte length), but when trying to run the above script using this structure, I get the following error:
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
I don’t understand why the authentication tag check fails.
Advertisement
Answer
Decryption fails for two reasons:
For PBKDF2 neither the iteration count nor the digest are explicitly specified, so the default values 1000 and SHA1 are used. However, the values to be applied are 160000 and SHA512 according to the documentation:
from Crypto.Hash import SHA512 ... mainKey = PBKDF2(key, salt, count=160000, hmac_hash_module=SHA512)
The salt is not authenticated, i.e. the line
cipher.update(salt)
must be removed.
With these changes, authentication and decryption is successful and decryptedData
is b'{"id": "123", "name": "Ronald"}'
.
Note that for GCM the length 16 bytes is allowed for the nonce/IV, but the recommended length is 12 bytes. But maybe a change is beyond your control.