Search code examples
javapythonencryptionaes-gcmpycryptodome

How can I convert this Java encryption code to python


I was trying to convert a java code to python. tried to use pycryptodome library for the purpose. This is java code:

try {
    String data= "shouldEncryptDATA";
    String bas64ed= "";
    int len12 = Integer.parseInt("12");
    byte[] randomparam= new byte[len12];
    new SecureRandom().nextBytes(randomparam);
    SecretKeySpec secretKeySpec= new SecretKeySpec("1f1f7892GKG38815".getBytes(), "AES");
    Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
    cipher.init(1, secretKeySpec, new GCMParameterSpec(Integer.parseInt("16") * 8, randomparam)); 
    byte[] bytedata= cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
    byte[] newbytearray= new byte[bytedata.length + len12];
    System.arraycopy(randomparam, 0, newbytearray, 0, len12); 
    System.arraycopy(bytedata, 0, newbytearray, len12, bytedata.length);
    bas64ed= Base64.getEncoder().encodeToString(newbytearray);
    System.out.println("bas64ed: "+bas64ed);
            
    System.out.println(URLEncoder.encode(bas64ed, "UTF-8"));
          
} catch (Exception unused_ex) {
    System.out.println();
    System.out.println("ERROR: " + unused_ex);
}

so far I tried below python code to mimic above java code:

import base64
from Crypto.Cipher import AES
import urllib.parse
from Crypto.Random import get_random_bytes

data= "shouldEncryptDATA"

key = b '1f1f7892GKG38815' 

len12 = 12
v1 = bytearray(len12)
                                         
cipher = AES.new(key, AES.MODE_GCM, nonce=get_random_bytes(12) ) 
ciphertext, tag = cipher.encrypt_and_digest(data.encode("utf8"))
base64ed = ""
for x in cipher.nonce, ciphertext, tag:
        base64ed += base64.b64encode(x).decode('utf-8')
urlencoded = urllib.parse.quote_plus(base64ed+"\n")

print(urlencoded )

the above python code generates an output but the problem is that when I supply the output to the decryption code I got MAC check Failed. so I realized my implementation in the python code is somewhat is the problem because the output of the Java code when passed to the decryption code, it works and decrypts the data. so How can I correctly convert the Java encryption code to Python? using the Pycryptodome or any other suitable library.


Solution

  • The bug in the Python code is in the concatenation, it must be:

    base64ed = base64.b64encode(cipher.nonce + ciphertext + tag).decode('utf-8')
    

    After this fix, if you compare the ciphertexts of both codes with identical input data (especially with identical IV), they are the same.