Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python AES decryption

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 :)

like image 372
Faur Ioan-Aurel Avatar asked Dec 27 '14 18:12

Faur Ioan-Aurel


People also ask

How do I decrypt AES encryption in Python?

AES requires a secret passphrase known as a “key” to encrypt/decrypt data. Anybody with the key can decrypt your data, so you need it to be strong and hidden from everyone―only the software program should be able to access it. The key can be either 128, 192, 256, or 512 bit long.

How do you implement AES encryption in Python?

Once pycrypto is installed, create a python file and write the following to import everything we need: Now we are going to create a class for our AES cipher with the following constructor: Lets take a quick walk through the constructor, it receives a key which can be of any length.


1 Answers

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.

like image 156
Artjom B. Avatar answered Sep 30 '22 04:09

Artjom B.