Search code examples
javapythonandroidencryptionaes

AES Encryption Different Result Java And Python


I have this android java AES encryption code that make my token, now i want to make it in python too, but some how it has different result.

java

private Void encrypt(String password) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, ShortBufferException, BadPaddingException, IllegalBlockSizeException {

    byte[] bytes = password.getBytes(StandardCharsets.UTF_8);

    SecretKeySpec secretKeySpec = new SecretKeySpec(MessageDigest.getInstance("MD5")
    .digest("mysecretkey".getBytes(StandardCharsets.UTF_8)), "AES");

    Cipher instance = Cipher.getInstance("AES/ECB/PKCS5Padding");
    instance.init(1, secretKeySpec);

    byte[] bArr = new byte[instance.getOutputSize(bytes.length)];

    instance.doFinal(bArr, instance.update(bytes,0,bytes.length, bArr, 0));


    for (byte b : bArr){

        Log.d("encrypt", String.valueOf(b));

    }
}

python

from Crypto.Cipher import AES

import hashlib


def pad(byte_array):
    BLOCK_SIZE = 16
    pad_len = BLOCK_SIZE - len(byte_array) % BLOCK_SIZE
    return byte_array + (bytes([pad_len]) * pad_len)


def encrypt(key, message):


    byte_array = message.encode("UTF-8")
    panjang = len(message)

    padded = pad(byte_array)

    cipher = AES.new(key.encode("UTF-8"), AES.MODE_ECB)
    encrypted = cipher.encrypt(padded)

    for b in encrypted:
        print(b)





password = "mypassword"

secret_key = "mysecretkey"
hashkey = hashlib.md5(secret_key.encode()).hexdigest()

encrypt(hashkey,password)

java result

-25 -16 84 -36 100 -102 74 -98 -91 -77 100 -96 -86 28 -47 -67

python result

220 127 95 142 45 102 9 79 170 82 165 2 63 39 196 7

i've been figuring out this for days but cant see where the problem is.


Solution

  • The actually correct values your going for, i.e. encrypting a (padded) block with "mypassword" with the AES-key MD5("mysecretkey"), this is

    e7 f0 54 dc 64 9a 4a 9e a5 b3 64 a0 aa 1c d1 bd

    viewed as hex. (produced with the standard openssl command line tool)

    The Java code actually shows the correct result: if the above is in a file p.enc (as it is on my PC), I can display it in signed bytes as

    od -An -t d1 p.enc and then I get

    -25 -16 84 -36 100 -102 74 -98 -91 -77 100 -96 -86 28 -47 -67

    which is your representation as well.

    In Python you wrongly use .hexdigest() instead of digest().

    hexdigest produces a 32 character string (with ASCII values, not raw binary) so your AES.new call gets a 256-bits key, not 128 bits and the result will be wrong (you'll use AES-256)

    You're not specifying what version of Python you're using. But in Python (2.7) you can reproduce the correct result (assuming your same imports from Crypto and hashlib) as

    key=hashlib.md5('mysecretkey').digest() plain='mypassword'+ '\006'*6 #manual padding addition for the example aes=AES.new(key, AES.AES_ECB) cipher=aes.encrypt(plain)

    which gets the abovementioned correct value.

    To view it in signed bytes (as Java does) for comparison's sake:

    [ord(b)-256 if ord(b)>127 else ord(b) for b in cipher]

    And the results then match up.