Search code examples
pythonlaravelencryptionaespycryptodome

AES Decryption in Python when IV and Value provided separately


I've got a encrypt/decrypt class setup based on this SO answer. I've tested it and it works fine. It's not working for a new API I'm pulling information from. The new API is built with PHP and is using the following package to encrypt information: https://laravel.com/docs/8.x/encryption using Laravel Crypt() command. All encrypted values are encrypted using OpenSSL and the AES-256-CBC cipher.

The enc value after the first line of the decrypt method

def decrypt(self, enc):
    enc = base64.b64decode(enc)
    iv = enc[:AES.block_size]
    cipher = AES.new(self.key, AES.MODE_CBC, iv)
    return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')

looks like this (Don't worry, this is just non-sensitive demo data):

b"{'iv': 'Ld2pjRJqoKcWnW1P3tiO9Q==', 'value': 'M9QeHtbybeUxAVuIRcQ3bA==', 'mac': 'xxxxxx......'}"

, which basically looks like a byte-string JSON. The testing encryption key is base64:69GnnXWsW1qnW+soLXOVd8Mi4AdXKBFfkw88/7F2kSg=.

I know I can turn it into a dictionary like this

import json
d = json.loads(enc)

How should I manipulate values from this dictionary to prepare it to be decrypted like other encrypted text this class can successfully decrypt?

Update:

Based on comments I've tried to modify the method to look like this:

def decrypt(self, encrypted):
    enc = base64.b64decode(encrypted)
    if b'{"iv":' == enc[:6]:
        d = json.loads(enc)
        iv = base64.b64decode(d['iv'])
        val = base64.b64decode(d['value'])
    else:
        iv = enc[:AES.block_size]
        val = enc[AES.block_size:]
    cipher = AES.new(self.key, AES.MODE_CBC, iv)
    return self._unpad(cipher.decrypt(val)).decode('utf-8')

This still does not work. It doesn't crash, but I'm getting a blank string back ('') and I know that's not what was encrypted. The answer should be 'Demo'


Solution

  • The code in the "Update" section of the question will work without any changes. You just need to make sure to remove the "base64:" prefix in the encryption key provided. Once that is removed, it will work as expected.