Search code examples
pythonjavaencryptionaes

AES/ECB/PKCS5Padding Encryption Different Result in Java And Python


Similar to this Java AES encryption code, I'm encrypting my data in python, however the results are different. I gave this some serious days. Would be very grateful for assistance here.

Java

public String encrypt(String strToEncrypt, String myKey) throws Exception {
        try
        {
            MessageDigest sha = null;
            byte[] key = myKey.getBytes("UTF-8");
            sha = MessageDigest.getInstance("SHA-1");
            key = sha.digest(key);
            key = Arrays.copyOf(key, 32);
            SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes("UTF-8")));
        } 

Python

import base64
import hashlib
from Crypto.Cipher import AES

def encrypt(str_to_encrypt, my_key):
    try:
        sha = hashlib.sha1()
        sha.update(my_key.encode('utf-8'))
        key = sha.digest()
        key = key[:16]  # AES-128
        cipher = AES.new(key, AES.MODE_ECB)
        byte_array = str_to_encrypt.encode("UTF-8")
        padded_data = pad(byte_array, AES.block_size)
        encrypted_data = cipher.encrypt(padded_data)
        return base64.b64encode(encrypted_data).decode('utf-8')
    except Exception as e:
        raise e

def pad(byte_array: bytearray, block_size: int):
    pad_len = block_size - len(byte_array) % block_size
    return byte_array + (bytes([pad_len]) * pad_len)


# Example usage:
my_key = "mySecretKey"
str_to_encrypt = "This is the string to encrypt"
encrypted_string = encrypt(str_to_encrypt, my_key)
print(encrypted_string)

java result

0xfLbMxzLp0B1v10jgySMuPsNn74Ow55x2R6GUyY9XE=

python result

jhfQIBB0vFeerfp1LdhZwIW/Bj6VXsPy84YWkci8oPA=

Solution

  • Must be the appended zeroes in key = Arrays.copyOf(key, 32);

    Python Original Key: [109, 121, 83, 101, 99, 114, 101, 116, 75, 101, 121]
    Python SHA-1 Digest (key): [170, 243, 150, 73, 152, 47, 173, 4, 165, 19, 82, 143, 200, 228, 115, 234]
    Python AES Key: [170, 243, 150, 73, 152, 47, 173, 4, 165, 19, 82, 143, 200, 228, 115, 234]
    
    Python Encrypted Data: [142, 23, 208, 32, 16, 116, 188, 87, 158, 173, 250, 117, 45, 216, 89, 192, 133, 191, 6, 62, 149, 94, 195, 242, 243, 134, 22, 145, 200, 188, 160, 240]
    
    
    
    // With key = Arrays.copyOf(key, 32);
    Java Original Key: [109, 121, 83, 101, 99, 114, 101, 116, 75, 101, 121]
    Java SHA-1 Digest: [-86, -13, -106, 73, -104, 47, -83, 4, -91, 19, 82, -113, -56, -28, 115, -22, 55, 38, 25, -70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    Java SHA-1 Digest (unsigned): 170, 243, 150, 73, 152, 47, 173, 4, 165, 19, 82, 143, 200, 228, 115, 234, 55, 38, 25, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    Java Secret Key: [-86, -13, -106, 73, -104, 47, -83, 4, -91, 19, 82, -113, -56, -28, 115, -22, 55, 38, 25, -70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    Java Secret Key (unsigned): 170, 243, 150, 73, 152, 47, 173, 4, 165, 19, 82, 143, 200, 228, 115, 234, 55, 38, 25, 186, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    Java Encrypted Bytes: [-45, 23, -53, 108, -52, 115, 46, -99, 1, -42, -3, 116, -114, 12, -110, 50, -29, -20, 54, 126, -8, 59, 14, 121, -57, 100, 122, 25, 76, -104, -11, 113]
    
    
    
    // With key = Arrays.copyOf(key, 16);
    Java Original Key: [109, 121, 83, 101, 99, 114, 101, 116, 75, 101, 121]
    Java SHA-1 Digest: [-86, -13, -106, 73, -104, 47, -83, 4, -91, 19, 82, -113, -56, -28, 115, -22]
    Java SHA-1 Digest (unsigned): 170, 243, 150, 73, 152, 47, 173, 4, 165, 19, 82, 143, 200, 228, 115, 234, 
    Java Secret Key: [-86, -13, -106, 73, -104, 47, -83, 4, -91, 19, 82, -113, -56, -28, 115, -22]
    Java Secret Key (unsigned): 170, 243, 150, 73, 152, 47, 173, 4, 165, 19, 82, 143, 200, 228, 115, 234, 
    Java Encrypted Bytes: [-114, 23, -48, 32, 16, 116, -68, 87, -98, -83, -6, 117, 45, -40, 89, -64, -123, -65, 6, 62, -107, 94, -61, -14, -13, -122, 22, -111, -56, -68, -96, -16]
    Java Encrypted Bytes (unsigned): 142, 23, 208, 32, 16, 116, 188, 87, 158, 173, 250, 117, 45, 216, 89, 192, 133, 191, 6, 62, 149, 94, 195, 242, 243, 134, 22, 145, 200, 188, 160, 240, 
    Encrypted Text: jhfQIBB0vFeerfp1LdhZwIW/Bj6VXsPy84YWkci8oPA=
    
    

    Since you can only modify the python code you need to pad the key up to 32 bytes like in the Java code:

    
    def encrypt(str_to_encrypt, my_key):
        try:
            sha = hashlib.sha1()
            sha.update(my_key.encode('utf-8'))
            key = sha.digest()
            key = key.ljust(32, b'\0')
            cipher = AES.new(key, AES.MODE_ECB)
            byte_array = str_to_encrypt.encode("UTF-8")
            padded_data = pad(byte_array, AES.block_size)
            encrypted_data = cipher.encrypt(padded_data)
            return base64.b64encode(encrypted_data).decode('utf-8')
        except Exception as e:
            raise e
    

    With key = key.ljust(32, b'\0') added we obtain the same output as the Java code 0xfLbMxzLp0B1v10jgySMuPsNn74Ow55x2R6GUyY9XE=