Search code examples
javascriptencryptionapigee3descbc-mode

How to encrypt text by 3DES, CBC mode using Javascript on APIGEE


Here is my information:

  • Plain Text: ---------------------------------------------------
    • do not encode
  • Key: ------------------------------------
    • do not encode
  • Ecryption Algorithm: 3DES, CBC mode with symmetric key
  • Init Vector : ------------------------------
    • I knew only "iv must be hexa form"

Desired Output:

----------------------------------------------------------------------------

I'm using this library: https://cdn.rawgit.com/CryptoStore/crypto-js/3.1.2/build/rollups/tripledes.js

My function to encrypt:

function encryptByDES(message, key){
  var iv = CryptoJS.lib.WordArray.create(8);
  var encrypted = CryptoJS.TripleDES.encrypt(message, key, {
    iv: key,
    mode: CryptoJS.mode.CBC
  });
  return encrypted.toString();
}

Actual Output:

----------------------------------------------------------------------------

Question: How do I achieve my desired output?


Solution

  • There are a number of oddities and issues with your inputs/outputs and code:

    • You have a Base64 plaintext which you pass as plain UTF8 (???), UTF8 encoded key and hex encoded IV. Ideally you should operate under one encoding for all three values. I recommend base64 if you can't operate using plain binary.

    • You're using a fixed IV, which introduces a number of vulnerabilities that can result in plaintext recovery. Always randomly generate an IV for each encryption operation.

    • You're passing the key as the IV during encryption, so the IV that you do generate is not used anyway. Never use the key as an IV.

    I have solved your issue and have produced the desired output but I am not going to post the code, as you won't learn anything. Instead I'll tell you what you need to do to fix what you have:

    • Modify your existing to code to actually use the IV.
    • Pass the plaintext and key as binary data to the encrypt function by using CryptoJS.enc.Utf8.parse to get each as binary words.
    • Output the result as hex and not as base64.

    EDIT: The code used to produce the desired result. Note the conversion from base64 to hex for the output variable:

    let iv = CryptoJS.enc.Hex.parse("0000000000000000");
    let pt = CryptoJS.enc.Utf8.parse("MjAxODAxMDQwOTM5MzgxMjM0NTY3ODkwMTIzNA==");
    let key = CryptoJS.enc.Utf8.parse("20180104093938xSpUoDU3Z0");
    
    let result = CryptoJS.TripleDES.encrypt(pt, key, {
        iv: iv,
        mode: CryptoJS.mode.CBC
    });
    
    let output = CryptoJS.enc.Hex.stringify(CryptoJS.enc.Base64.parse(result.toString()));
    console.log(output);