1

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.

1 Answer 1

1

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.

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

3 Comments

@hanan - Both codes provide different ciphertexts for each encryption. This is due to the random IV and is necessary for security reasons. So if you want to compare the ciphertexts of Java and Python code, you have to use identical IVs (for testing only, of course)! Another possibility for verification is the decryption.
while the code you shared is correct but when I supply the output of java code to the server it worked fine but the output of the python code it returns Invalid Input Data. I mean is it the problem the IV ? the java side it is generated using new GCMParameterSpec(Integer.parseInt("16") * 8, randomparam)? right? but in python I don't know how can I do this? the get_randombytes(12) was just guessing and trying.
Both lines generate random (and thus of course different) 12 bytes IVs, which is quite correct! The IV is concatenated with the ciphertext so that it is available during decryption. Also, on my machine, the Java and Python code produce identical ciphertexts when the same plaintext, the same key, and especially the same IV are applied. If it is different for you, you should post an example: plaintext, key, IV and ciphertext of both codes.

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.