Search code examples
pythontypescriptaescryptojspycrypto

AES-256-CBC returns a 32 byte cipher with cryptoBrowserify but returns a 48 byte cipher with PyCrypto


I've been trying to encrypt and decrypt data that has been sent to/from the client for a bit. In typescript, I have the following:

const AES_BLOCK_SIZE = 16;
const ZERO_IV = Buffer.alloc(AES_BLOCK_SIZE);

var cipher = cryptoBrowserify.createCipheriv('aes-256-cbc', key, ZERO_IV);
buf = cipher.update(data);

Where data, buf and key should be 32 bytes, and ZERO_IV should be 16 bytes.

I need to replicate this encryption in Python 3.12, however this is my attempt:

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

ZERO_IV = bytes([0] * 16)
def encrypt_buffer(key, buf):
    cipher = AES.new(key, AES.MODE_CBC, ZERO_IV)

    encrypted_buf = cipher.encrypt(pad(buf, 16))
    return encrypted_buf

If I were to put the same data, key, and iv into both, the Python version would return a bytes object with 48 bytes rather than 32. What exactly have I done wrong with the Python implementation?

Apologies, but I have absolutely no clue when it comes to ts/js, nor will I be able to modify it.

I'm pretty stumped with this one, so any help will be greatly appreciated!


Solution

  • The JavaScript code forgets the call to final. This translates to 32 byte encryption without padding.

    In principle update might even keep data buffered internally - nothing in the API suggests that this is not allowed, but in general - for CBC mode - the data is only buffered until a full block can be encrypted. That means that all your data should have been encrypted as 32 bytes is exactly 2 blocks of data.

    If padding is assumed when decrypting then the a padding error is likely thrown. However, in certain conditions, e.g. if the plaintext ends with a valid padding then only partial plaintext may be returned.

    For now the solution would be to simply remove all the padding from the Python code though. In the long run this code needs to be replaced, preferably by authenticated encryption such as AES in GCM mode, and of course using a zero-IV should be avoided.