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.
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.