4

I am working on the problem to encrypt the message using Java, then decrypt the message using Python based on AES GCM algorithm.

Based on python doc, the authentication tag is proved by encryptor. https://cryptography.io/en/latest/hazmat/primitives/symmetric-encryption/#cryptography.hazmat.primitives.ciphers.modes.GCM However, in Java, I donot know how authentication tag is generated.

Here is my Java code example

public class Example {

    public static final int AES_KEY_SIZE = 128; // in bits
    public static final int GCM_NONCE_LENGTH = 12; // in bytes
    public static final int GCM_TAG_LENGTH = 16; // in bytes

    public static void main(String args[]) throws Exception {

        byte[] message = "Hello".getBytes(StandardCharsets.UTF_8);

        SecureRandom secureRandom = SecureRandom.getInstanceStrong();
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(AES_KEY_SIZE, secureRandom);
        SecretKey secretKey = keyGenerator.generateKey();

        // Encrypt
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
        final byte[] nonce = new byte[GCM_NONCE_LENGTH];
        secureRandom.nextBytes(nonce);
        GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, nonce);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);

        byte[] tag = "World".getBytes(StandardCharsets.UTF_8);
        cipher.updateAAD(tag);
        byte[] cipherText = cipher.doFinal(message);

        System.out.println(Base64.getEncoder().encodeToString(secretKey.getEncoded()));
        System.out.println(Base64.getEncoder().encodeToString(nonce));
        System.out.println(Base64.getEncoder().encodeToString(tag));
        System.out.println(Base64.getEncoder().encodeToString(cipherText));

        cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
        cipher.updateAAD(tag);
        byte[] plainText = cipher.doFinal(cipherText);

        System.out.println(new String(plainText));
    }
}

Here is my Python code, which doesnot work, because "ValueError: Authentication tag must be provided when decrypting. "

    key = base64.b64decode("X3uBZOZdPqJipDsyvCm/zQ==");
    iv = base64.b64decode("Oe6yP87rg8G7dJSj");
    tag = base64.b64decode("V29ybGQ=");
    print (tag)
    msg = base64.b64decode("UvqFC+sWspXrWwdV6XCc7Wahp6l5");

    deCipher = Cipher(algorithms.AES(key), modes.GCM(iv, None), default_backend()).decryptor()
    deCipher.authenticate_additional_data(tag)
    computed_msg = deCipher.update(msg) + deCipher.finalize()
    print (computed_msg)

Given key, tag, nonce and cipherText, my question is how to write python code to decrypt the message?

Legorooj
  • 2,646
  • 2
  • 15
  • 35
Turbocv
  • 41
  • 4
  • 1
    Authentication tag and additional authenticated Data (AAD) are two different things. The tag-variable in both codes actually denotes the AAD and should be renamed accordingly. Furthermore, Java appends the authentication tag to the ciphertext. Since in Python authentication tag and ciphertext are passed separately, both variables have to be separated in Python first e.g. with `ciphertext = msg[:-16]` and `authTag = msg[-16:]`. Take a look at [this](https://cryptography.io/en/latest/hazmat/primitives/symmetric-encryption/#cryptography.hazmat.primitives.ciphers.modes.GCM). – Topaco Nov 12 '19 at 14:20
  • Thanks, test the code and it works. – Turbocv Nov 12 '19 at 16:16

1 Answers1

0

Thank you for the lead @topaco. Pasting the working code here.

import base64

from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes

def decrypt():    
    key = base64.b64decode("X3uBZOZdPqJipDsyvCm/zQ==")
    iv = base64.b64decode("Oe6yP87rg8G7dJSj")
    tag = base64.b64decode("V29ybGQ=")
    print(tag)
    msg = base64.b64decode("UvqFC+sWspXrWwdV6XCc7Wahp6l5")
    ciphertext, authTag = msg[:-16], msg[-16:]
    print(ciphertext, authTag)

    deCipher = Cipher(algorithms.AES(key), modes.GCM(iv, None, len(authTag)), default_backend()).decryptor()
    deCipher.authenticate_additional_data(tag)
    computed_msg = deCipher.update(ciphertext) + deCipher.finalize_with_tag(authTag)
    print(computed_msg)

if __name__ == '__main__':
   decrypt()
Roopak A Nelliat
  • 2,009
  • 3
  • 19
  • 26