0

I am trying to pass data between Python and Node.js application. For that i am using AES encryption. The problem is that Node.js produces encrypted data which is twice longer than the one produced using Python.

Below are code snippets.

Python 3.6

import binascii
from Crypto.Cipher import AES

key = 'key-xxxxxxxxxxxxxxxxxxZZ'
iv = '1234567812345678'
data = 'some_secret_data'

def _encrypt(data):
    aes = AES.new(key, AES.MODE_CBC, iv[:16])
    encrypted = aes.encrypt(data)
    # encrypted = b'\xd54\xbb\x96\xd3\xbet@\x10\x01 [\reg\xaa'

    encrypted_base64 = binascii.b2a_base64(encrypted)
    # encrypted_base64 = b'1TS7ltO+dEAQASBbDWVnqg==\n'

    encrypted_hex = binascii.hexlify(encrypted)
    # encrypted_hex = b'd534bb96d3be74401001205b0d6567aa'

    return encrypted_base64

output = _encrypt(data)

Node v6.10.0

let crypto = require("crypto");
let enc = require("./encryption");

var key = 'key-xxxxxxxxxxxxxxxxxxZZ';
var iv = '1234567812345678';
var data = 'some_secret_data';

var encrypted_hex = encrypt(data, 'hex');
var encrypted_base64 = encrypt(data, 'base64');

console.log(encrypted_hex);
// encrypted_hex = 'd534bb96d3be74401001205b0d6567aab4c31f7a76936598e5a1cc05385f3a91'

console.log(encrypted_base64);
// encrypted_base64 = '1TS7ltO+dEAQASBbDWVnqrTDH3p2k2WY5aHMBThfOpE='

function encrypt(msg, encoding){
    var aes = crypto.createCipheriv('aes-192-cbc', key, iv);
    var crypted = aes.update(msg,'utf8', encoding)
    crypted += aes.final(encoding);

    return crypted;
}

As you can see above, Python produces encrypted_hex which equals to d534bb96d3be74401001205b0d6567aa. In Node, encrypted_hex contains the value mentioned above + b4c31f7a76936598e5a1cc05385f3a91.

Could anyone help me understand what is going on here: Why does Node.js produces result which is twice longer ?

Termos
  • 664
  • 1
  • 7
  • 31
  • Since you're specifying AES 192 in node, is it possible you have a keysize mismatch, so your key is smaller in python (say, 128) and node fills up the gaps with a blank? Just a thought. – Keef Baker Apr 03 '17 at 10:20

1 Answers1

0

I figured it out. This happens because of different behavior of Pythons' PyCrypto package and Nodes' Crypto module. I am using AES, and since it is a block cypher, it requires data to come in chunks of specified length.

PyCrypto fails if it encounters data which doesn't come in 16 bit chunks. Nodes' Crypto, by default will pad data, so data will always come in chunks of good size.

For the sake of simplicity i've tested data having length of 16 bytes in the examples above. So why were the results different?

Python module did not pad data by default, and because data contained correct length, we've got expected result.

Node Crypto module, however, does pad the data, and apparently adds the whole 16 bit chunk of padding to original message (which really sounds like a bug). That is why the first part of encrypted Nodes' message corresponds to the one created in Python, the other one is just Node Crypto trying to encrypt its own excessive padding.

Anyway, to get rid of the error, i've simply added

 aes.setAutoPadding(false);

in my encrypt() function.

Wooh.

Termos
  • 664
  • 1
  • 7
  • 31
  • Please don't disable padding. You really should enable padding and [implement](http://stackoverflow.com/a/12525165/1816580) it in Python as well. – Artjom B. Apr 03 '17 at 17:00