Search code examples
javascriptencryptioncryptojs

Decryption of TripesDES algorithm in CryptoJS returns nothing


I tried encrypting a data using TripleDES in CryptoJS library. I created an encryption example using this tool https://www.devglan.com/online-tools/triple-des-encrypt-decrypt and generated a string encryption data of NbU4PoYHR9IJtSLmHRubpg==

Now I want to decrypt this NbU4PoYHR9IJtSLmHRubpg== generated from the site using javascript code with CryptoJS library.

I have generated also a SharedKey with this string 36fd14ddcd755bb37879cbe99ca26c92

Here is my code:

export const decryptData = (params) => {
    const {ClientSecret, ApiKey} = params;    
    const SharedKey = `${ClientSecret}:${ApiKey}`;
    const data = 'NbU4PoYHR9IJtSLmHRubpg==';
  
    let CryptoSharedKey = CryptoJS.MD5(SharedKey).toString();
    const ct = CryptoJS.enc.Base64.parse(data);
  
    console.log('decrypt',CryptoJS.TripleDES.decrypt(ct, CryptoSharedKey).toString(CryptoJS.enc.Utf8))
}

now the problem is when i console log the result, it gives me nothing but an empty string.


Solution

  • The web tool simply UTF-8 encodes the key, so in the CryptoJS code the key derivation via MD5 must be removed.

    Also, the web tool automatically truncates too long keys to 24 bytes, the key length used by TripleDES in the 3TDEA variant. Since the key you apply is 32 bytes in size, it is truncated accordingly. CryptoJS also shortens keys that are too long implicitly (though it is more transparent to shorten them explicitly).

    Furthermore, in the CryptoJS code, the key material must be passed as WordArray to be interpreted as key (if passed as string, it will be interpreted as password and a key derivation function will be applied). For conversion to a WordArray the key has to be parsed with the Utf8 encoder.

    In addition, the ciphertext must be passed as CipherParams object or Base64 encoded (the latter is implicitly converted to a CipherParams object).

    Moreover, since the ECB mode was used for encryption in the web tool, this mode must also be applied in the CryptoJS code. For this, ECB must be explicitly set, since CBC is the CryptoJS default.

    Hence, the code is to be changed as follows:

    var key = CryptoJS.enc.Utf8.parse('36fd14ddcd755bb37879cbe99ca26c92'.substr(0, 24)); // Explicitly shorten the key to 24 bytes; parse the key into a WordArray
    var data = 'NbU4PoYHR9IJtSLmHRubpg==';
    var decrypted = CryptoJS.TripleDES.decrypt(data, key, {mode: CryptoJS.mode.ECB}); // Pass data Base64 encoded; apply ECB mode (default is CBC)
    console.log('decrypt: ', decrypted.toString(CryptoJS.enc.Utf8));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

    Note that TripleDES is outdated and that ECB is insecure.