decrypting CyproJS AES encryption in Cryptodome python

831 views Asked by At

I am trying to decrypt message (in python) that has been encoded using CryptoJS in JavaScript. I have created an API in python, to post data I am using postman pre-request script.

The Error I am getting:

ValueError: Data must be padded to 16 byte boundary in CBC mode

JavaScript code for encryption

var data = {"feature_0": 0,
            "feature_1": 0, 
            "feature_2": 0, 
            "feature_3": 0, 
            "feature_4": 0, 
            "feature_5": 0
           };
let password = "lazydog";
let salt = "salt";
let iterations = 128;
data = JSON.stringify(data);
let len = 16 - ((data.length) % 16);
data += len.toString().repeat(len);  --> removed (as suggested)
let bytes = CryptoJS.PBKDF2(password, salt, { keySize: 48, iterations: iterations });
let iv = CryptoJS.enc.Hex.parse(bytes.toString().slice(0, 32));
let key = CryptoJS.enc.Hex.parse(bytes.toString().slice(32, 96));

let encrypted = CryptoJS.AES.encrypt(data, key, {iv: iv}); //, mode: CryptoJS.mode.CBC
//encrypted = btoa(encrypted); --> removed (as suggested)
encrypted = encrypted.toString() -->added (as suggested)
postman.setGlobalVariable("data", encrypted);

python code for decryption:

def decode(encrypted):
    data = b64decode(encrypted)  
    byte = PBKDF2("lazydog".encode("utf-8"), "salt".encode("utf-8"), 48, 128)
    iv = byte[0:16]
    key = byte[16:48]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    text = cipher.decrypt(data) ## error is at this line
    text = text[:-text[-1]].decode("utf-8")

    return text

As the error said padding problem I added padding in JS code. Still I am not getting good results. What's wrong I am doing here?

1

There are 1 answers

0
D1V On BEST ANSWER

The encrypted string has posted to API which has written in python. I don't know why but when encrypted passed to python '+' chars are being replaced with ' '(space). By replacing the spaces with '+' char I resolved the problem.

code

var data = {"feature_0": 0,
        "feature_1": 0, 
        "feature_2": 0, 
        "feature_3": 0, 
        "feature_4": 0, 
        "feature_5": 0
       };
let password = "lazydog";
let salt = "salt";
let iterations = 128;
data = JSON.stringify(data);
let bytes = CryptoJS.PBKDF2(password, salt, { keySize: 48, iterations: 
  iterations });
let iv = CryptoJS.enc.Hex.parse(bytes.toString().slice(0, 32));
let key = CryptoJS.enc.Hex.parse(bytes.toString().slice(32, 96));

let encrypted = CryptoJS.AES.encrypt(data, key, {iv: iv});
encrypted = encrypted.toString()
postman.setGlobalVariable("data", encrypted);

python code

def decode(encrypted):
    encrypted = encrypted.replace(' ', '+') --> this line is added
    data = b64decode(encrypted)  
    byte = PBKDF2("lazydog".encode("utf-8"), "salt".encode("utf-8"), 48, 128)
    iv = byte[0:16]
    key = byte[16:48]
    cipher = AES.new(key, AES.MODE_CBC, iv)
    text = cipher.decrypt(data) ## error is at this line
    text = text[:-text[-1]].decode("utf-8")

    return text

As CryptoJs pads data implicitly custom padding has been removed. And removed btoa (which is not required). Then encrypted data is converted to String. suggested by @Topaco in the comments