5

I have the following piece of code in Java that I want to replicate in Python.

public class AESDecryption { protected SecretKeySpec getPublicKey() { try { byte[] key = "MuidKeibimbtjph9".getBytes("UTF-8"); key = MessageDigest.getInstance("SHA-256").digest(key); key = Arrays.copyOf(key, 32); return new SecretKeySpec(key, "AES"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } public String decrypt(byte[] data) { Cipher cipher = null; try { cipher = Cipher.getInstance("AES/CBC/NoPadding"); cipher.init(2, new SecretKeySpec(getPublicKey().getEncoded(), "AES"), new IvParameterSpec(new byte[cipher.getBlockSize()])); byte decryptedBytes[] = cipher.doFinal(data); return new String(Arrays.copyOf(decryptedBytes, decryptedBytes.length - decryptedBytes[-1 + decryptedBytes.length])); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } return ""; } public static void main(String[] args) { try { byte[] content = Files.readAllBytes(Paths.get("/tmp/dump.gzip")); AESDecryption aesDecryption = new AESDecryption(); System.out.println(aesDecryption.decrypt(content)); } catch (IOException e) { e.printStackTrace(); } } } 

This code comes from a client application. I have no power on the server side where the encrypted content is generated. For this question I've changed the symmetric key and how the content is retrieved( in this example from a file but in reality from an https response)

I want to replicate this functionality in a python script using the PyCrypto library. This is how my initial code looks like:

from Crypto.Cipher import AES from Crypto.Hash import SHA256 from Crypto import Random BLOCK_SIZE = 16 unpad = lambda s: s[0:-ord(s[-1])] hash = SHA256.new() hash.update('MuidKeibimbtjph9') symmetric_key = hash.digest() symmetric_key = symmetric_key[:32] bytes_store = None with open('/tmp/dump.gzip','r') as f: bytes_store = f.read() rndfile = Random.new() aes_decryptor = AES.new(symmetric_key, AES.MODE_CBC, rndfile.read(BLOCK_SIZE)) print unpad(aes_decryptor.decrypt(bytes_store)) 

Running the java code on the encrypted file works just fine. The result looks somehting like:

{"code":200,"status":"ok","api_version":"0.0.0","data":[.....],"notifications":{}} 

However the python replication dumps a "half decrypted" text. Well sort of..

=c�q[A�$�dl�tus":"ok","api_version":"0.0.0","data":[.....],"notifications":{}} 

I can't make anything out of it. Looking at the Java code it is clear that there is no padding in the cipter block, so I thought that probably the data on the server side is already a multiple of the cipher block size. There was also a lot of ▯▯▯ characters at the end of python output but I quickly got rid of them by unpadding decrypted data. Still, I can't figure out what I'm doing wrong that the first part of the payload is scrambled. My knowledge about data encryption is pretty basic, thus I'm reaching to you for knowledge :)

1 Answer 1

5

The problem is that the server code uses a fixed IV (which is bad) with zeroes in it, but in your python code, you pass a new randomly generated IV to AES.new.

You can replace rndfile.read(BLOCK_SIZE) with "\x00"*BLOCK_SIZE.

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

3 Comments

I agree that the Python code uses a random IV while the Java code appears not to, but if that were the problem, wouldn't the "half-decrypted" text be complete jibberish?
@unutbu: In CBC mode only the first block will be affected in the decrypt direction. P_n = D(C_n) xor C_n-1.
Awesome, thanks. Now after reading more carefully the wikipedia article on CBC mode - it does says that the IV must be correct for CBC otherwise the first block of plaintext will be corrupt but subsequent plaintext blocks will be correct.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.