Search code examples
javascriptpythonpycryptocryptojs

pyCrypto: Input must be a multiple of 16 in length


I am trying to decrypt a string encoded with "crypto-js" and decode it in python using "pyCrypto". I have followed the exact steps on various blogs but still the same error.

Last stackoverflow post i followed was "CryptoJS and Pycrypto working together" the answer given by @Artjom B.

Also tried "https://chase-seibert.github.io/blog/2016/01/29/cryptojs-pycrypto-ios-aes256.html"

My js code is

var pass = CryptoJS.AES.encrypt(text, password_encrypt_key, 
        {
            iv: password_encrypt_iv,
        })
    return password_encrypt_iv.concat(pass.ciphertext).toString(CryptoJS.enc.Base64);

And my python code is

    BLOCK_SIZE = 16
    KEY = constants.PASSWORD_ENCRYPT_KEY
    # IV = constants.PASSWORD_ENCRYPT_IV
    IV = enc_password[:BLOCK_SIZE]
    MODE = AES.MODE_CBC
    enc_password = base64.b64decode(enc_password)
    aes = AES.new(KEY, MODE, IV)
    password = unpad(aes.decrypt(enc_password[BLOCK_SIZE:]))

unpad function

def unpad(s):
  return s[:-ord(s[-1])]

Solution

  • I found the solution. Not sure how this worked and not the rest of the solution but anyways posting it. Also the solution is from the below link answer by Artjom B. He has given better explaination. I am also posting the same answer.

    Link - How to decrypt password from JavaScript CryptoJS.AES.encrypt(password, passphrase) in Python

    Javascript -

    var KEY = encrypt_key;
    var encrypted_txt_obj = CryptoJS.AES.encrypt(text, KEY);
    return encrypted_txt_obj.toString();
    

    python -

    from Crypto.Cipher import AES
    import base64
    
    BLOCK_SIZE = 16
    
    def bytes_to_key(data, salt, output=48):
        data += salt
        key = md5(data).digest()
        final_key = key
        while len(final_key) < output:
          key = md5(key + data).digest()
          final_key += key
        return final_key[:output]
    
    def decrypt_text(enc):
        try:
            enc = base64.b64decode(enc)
            assert enc[0:8] == b"Salted__"
            salt = enc[8:16]
            key_iv = bytes_to_key(encrypt_key, salt, 32 + 16)
            key = key_iv[:32]
            iv = key_iv[32:]
            aes = AES.new(key, AES.MODE_CBC, iv)
            text = unpad(aes.decrypt(enc[16:]))
            return text
       except Exception as e:
            resp = jsonify({constants.ERR_SERVER: e.message})
            resp.status_code = 403
            logger.error("Exception %s", e.message)
            return resp
    
    def unpad(data):
        return data[:-(data[-1] if type(data[-1]) == int else ord(data[-1]))]