skip to Main Content

I have a JavaScript Encryption Algorithm, which I am trying to convert into Python. I tried studying the algorithm, though it is not too much complex but I am unable to fully understand and convert it to the Python code. The JavaScript code is

var grecaptcha = [];
enc = function (a) {
var keyBytes = CryptoJS.PBKDF2('lrvq/wyDf6tqhxvg8NuIDQ==', 'Ivan Medvedev', { keySize: 48 / 4, iterations: 1000 });
// take first 32 bytes as key (like in C# code)
var key = new CryptoJS.lib.WordArray.init(keyBytes.words, 32);
// skip first 32 bytes and take next 16 bytes as IV
var iv = new CryptoJS.lib.WordArray.init(keyBytes.words.splice(32 / 4), 16);
// use the same encoding as in C# code, to convert string into bytes
var data = CryptoJS.enc.Utf16LE.parse(a);
var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv });
$("#capBBC").val(encrypted.toString());
}

The Python code that I was able to write is

from Crypto.Protocol.KDF import PBKDF2
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def enc(a):
    key = PBKDF2("lrvq/wyDf6tqhxvg8NuIDQ==", "Ivan Medvedev", dkLen=48, count=1000)
    iv = key[32:]
    data = a.encode('utf-16le')
    
    cipher = AES.new(key, AES.MODE_CBC, iv)
    encrypted = cipher.encrypt(pad(data, AES.block_size))
    
    return encrypted.hex()

print(enc("Cat"))

This code raise the following exception

Traceback (most recent call last):
  File "C:UsersFarhan AhmedDesktopcodePythonKiara Snickersdel.py", line 16, in <module>
    print(enc("Cat"))
  File "C:UsersFarhan AhmedDesktopcodePythonKiara Snickersdel.py", line 11, in enc
    cipher = AES.new(key, AES.MODE_CBC, iv)
  File "C:UsersFarhan AhmedAppDataLocalProgramsPythonPython310libsite-packagesCryptoCipherAES.py", line 232, in new
    return _create_cipher(sys.modules[__name__], key, mode, *args, **kwargs)
  File "C:UsersFarhan AhmedAppDataLocalProgramsPythonPython310libsite-packagesCryptoCipher__init__.py", line 79, in _create_cipher
    return modes[mode](factory, **kwargs)
  File "C:UsersFarhan AhmedAppDataLocalProgramsPythonPython310libsite-packagesCryptoCipher_mode_cbc.py", line 274, in _create_cbc_cipher
    cipher_state = factory._create_base_cipher(kwargs)
  File "C:UsersFarhan AhmedAppDataLocalProgramsPythonPython310libsite-packagesCryptoCipherAES.py", line 93, in _create_base_cipher
    raise ValueError("Incorrect AES key length (%d bytes)" % len(key))
ValueError: Incorrect AES key length (48 bytes)

I do not know what should be value of dkLen
Thanks for any help in advance.

2

Answers


  1. keySize: 48 / 4 in your js code, so I suggest that it is 12 for your python code

    upd:

    keyBytes = PBKDF2(password, salt, dkLen=48, count=1000)
    key = keyBytes[:32]
    iv = keyBytes[32:48]
    
    Login or Signup to reply.
  2. In the CryptoJS code the first 32 bytes of the data returned by PBKDF2 are used as key, but in the Python code the entire data.
    This is 48 bytes large, which does not correspond to a valid AES key and thus causes the error Incorrect AES key length (48 bytes).
    Also, the ciphertext in the CryptoJS code is returned Base64 encoded and not hex encoded.

    A possible fix for both is:

    from Crypto.Protocol.KDF import PBKDF2
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    import base64
    
    def enc(a):
        keyIv = PBKDF2("lrvq/wyDf6tqhxvg8NuIDQ==", "Ivan Medvedev", dkLen=48, count=1000)
        key = keyIv[:32]
        iv = keyIv[32:]
        data = a.encode('utf-16le')
        
        cipher = AES.new(key, AES.MODE_CBC, iv)
        encrypted = cipher.encrypt(pad(data, AES.block_size))
        
        return base64.b64encode(encrypted).decode('utf-8')
    
    print(enc("Cat")) # CZ/1nUYEjhw4cFj08Yt1EQ==
    

    which returns a ciphertext corresponding to that of the CryptoJS code:

    enc = function (a) {
        var keyBytes = CryptoJS.PBKDF2('lrvq/wyDf6tqhxvg8NuIDQ==', 'Ivan Medvedev', { keySize: 48 / 4, iterations: 1000 });
        // take first 32 bytes as key (like in C# code)
        var key = new CryptoJS.lib.WordArray.init(keyBytes.words, 32);
        // skip first 32 bytes and take next 16 bytes as IV
        var iv = new CryptoJS.lib.WordArray.init(keyBytes.words.splice(32 / 4), 16);
        // use the same encoding as in C# code, to convert string into bytes
        var data = CryptoJS.enc.Utf16LE.parse(a);
        var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv });
        console.log(encrypted.toString());
    }
    enc("Cat")
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search