4

I use the AES method to encrypt a sentance called from a txt file. I used the GCM Mode and created a specific key too. Everything is working (the code is below).

from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
from Crypto.Util.number import long_to_bytes

number = 1
flag = open("sentance.txt", "rb").read()
key = scrypt(long_to_bytes(number), b"code", 32, N = 2 ** 10, r = 8, p = 1)
HexMyKey = key.hex()
cipher = AES.new(key, AES.MODE_GCM)
ciphertext, tag = cipher.encrypt_and_digest(flag)

enc = cipher.nonce + ciphertext + tag
HexEncryptedOriginalMessage = enc.hex()

I try to implement the decryption process, that is to say I only have the key (HexMyKeyvalue) and the encrypted message (HexEncryptedOriginalMessage value) and I want to decrypt it. But the thing is that I miss something ..
I wrote the code below but I have that error message.

TypeError: decrypt_and_verify() missing 1 required positional argument: 'received_mac_tag

from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
from Crypto.Util.number import long_to_bytes

key = bytes.fromhex(HexMykey)
data = bytes.fromhex(HexEncryptedOriginalMessage)
cipher = AES.new(key, AES.MODE_GCM)
dec = cipher.decrypt_and_verify(data)

Do you know how I could decrypt that encrypted original message ?
Any help would be greatly appreciated !

5
  • 1
    looks like you are missing the second argument to the decrypt_and_verify function which is mac_tag. Docs Commented Apr 28, 2021 at 21:00
  • 1
    On encryption side you concatenated the enc value with "enc = cipher.nonce + ciphertext + tag" so for decryption you need to do reverse = split the data (= complete ciphertext) into nonce, ciphertext and gcmTag and feed them to cipher.decrypt Commented Apr 28, 2021 at 21:03
  • 1
    github.com/wolf43/AES-GCM-example/blob/master/aes_gcm.py Commented Apr 28, 2021 at 23:19
  • Thank you both of you for your answers. @Michael Ok I understand I have to split the enc part but I don't know how to do. I tried ciphertext, tag, nonce = data but I got the following error message ValueError: too many values to unpack (expected 3). Have you got some ideas ? Commented Apr 29, 2021 at 5:45
  • @kelalaka I checked your link too and there is the split part too. But I didn't manage to implement it in my code.. Commented Apr 29, 2021 at 5:46

1 Answer 1

6

PyCryptodome has a good documentation. The GCM example there uses JSON for concatenating/separating nonce, ciphertext, and tag, but the principle is the same and can easily be applied to your code.

Since you are using the implicitly derived nonce, be aware that PyCryptodome applies a 16 bytes nonce. Note, however, that the recommendation for GCM is a 12 bytes nonce (s. here, Note section).

The following decryption example uses a key and ciphertext created with the code you posted for encryption:

from Crypto.Cipher import AES
HexMyKey = '6f9b706748f616fb0cf39d274638ee29813dbad675dd3d976e80bde4ccd7546a'
HexEncryptedOriginalMessage = '6b855acc799213c987a0e3fc4ddfb7719c9b87fcf0a0d35e2e781609143b6e2d8e743cf4aea728002a9fc77ef834'
key = bytes.fromhex(HexMyKey)
data = bytes.fromhex(HexEncryptedOriginalMessage)
cipher = AES.new(key, AES.MODE_GCM, data[:16]) # nonce
try:
    dec = cipher.decrypt_and_verify(data[16:-16], data[-16:]) # ciphertext, tag
    print(dec) # b'my secret data'
except ValueError:
    print("Decryption failed")

If authentication fails, decrypt_and_verify() generates a ValueError.

PyCryptodome also allows for GCM decryption without prior authentication:

cipher = AES.new(key, AES.MODE_GCM, data[:16]) # nonce
dec = cipher.decrypt(data[16:-16]) # ciphertext
print(dec) # b'my secret data'

However, this should not be done for GCM for security reasons, since a ciphertext is only trustworthy after successful authentication.

Furthermore, the encryption and decryption codes are somewhat inconsistent in that the encryption uses scrypt as the key derivation function and the decryption uses the derived key directly. Normally, one would expect that the key is also derived during decryption. Possibly you take this shortcut only for testing purposes.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you very very much for your exhaustive answer, that's perfectly clear for me. Actually I did not take care to the 16 bytes nonce, didn't take care to it, to be honest..I used it in my script and it works like a charm, now I can decrypt the original encrypted message ! Thanks !!
I think this code must include the tag verification, too.
@kelalaka: decrypt_and_verify() throws an exception, I added the exception handling
Way better, thanks. And be aware that GCM is very fragile, now partition oracles
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.