DISCLAIMER: This is INSECURE encryption that I've inherited and everyone involved knows that. What I'm trying to do here is a first step in getting off this legacy system that has even bigger problems that this.
I have an existing system in Java that I am attempting to port to Python that performs an AES encryption as such:
public static String encrypt(String text, SecretKey secretKey) throws Exception {
byte[] cipherText = null;
String encryptedString = null;
// get an RSA cipher object and print the provider
Cipher cipher = Cipher.getInstance(SYMMETRIC_KEY_ALGORITHM); // AES
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
cipherText = cipher.doFinal(text.getBytes());
encryptedString = Base64.getEncoder().encodeToString(cipherText);
return encryptedString;
}
The problem I'm having is trying to get the same combination of AES settings to get the same result using Python and the Cryptography library from:
I see lots of examples from the seemingly defunct PyCrypto library which I cannot even get to install on my Windows system much less work.
My latest attempt is like this and I do get encryption but it doesn't match the Java AES output:
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
key = b'Some random key '
cipher = Cipher(algorithms.AES(key), modes.GCM(b'000000000000'))
encryptor = cipher.encryptor()
ct = encryptor.update(ENC_MESSAGE)
base64EncodedStr = base64.b64encode(ct).decode('utf-8')
print('BASE64:', base64EncodedStr)
Update based on rzwitserloot's answer.
I changed the mode from GCM to ECB and the result I'm now getting in Python is almost the same. First of all here is what the updated code looks like:
key = b'Some random key '
cipher = Cipher(algorithms.AES(key), modes.ECB())
encryptor = cipher.encryptor()
ct = encryptor.update(PLAINTEXT.encode('utf-8'))
base64EncodedStr = base64.b64encode(ct).decode('utf-8')
print('Encrypted:', base64EncodedStr)
The reference (i.e. Java) output is 1004 characters long while the Python output is only 984 characters long. But up to 3 characters from the end of the Python string they match:
I did check with decryption and found that both encrypted text string decrypt to the same plaintext.
FINAL UPDATE:
The padding was the problem. I updated the code to use PKCS7 padding like this and I am now getting the same result from Java and Python:
from cryptography.hazmat.primitives import padding as symmetric_padding
padder = symmetric_padding.PKCS7(algorithms.AES.block_size).padder()
padded_data = padder.update(PLAINTEXT.encode('utf-8')) + padder.finalize()
ct = encryptor.update(padded_data)

SYMMETRIC_KEY_ALGORITHM? If it is literally just "AES", this code was entirely insecure and you don't want to port it. You want to find everything encrypted with it and notify that it's all to be considered compromised (AES defaults to ECB mode, which is a problem).