Jonathan Naguin
Jonathan Naguin

Reputation: 14786

TripleDES implementation in Javascript different comparing with C#

I need to replicate the following C# method to encrypt some text from Javascript. Currently I am using Crypto JS, but the output from JS is not equals to the C# output.

const string EncryptKey = "hello";

private static String getHexStringFromArray(byte[] arr) {
    StringBuilder sBuilder = new StringBuilder();

    for (int i = 0; i < arr.Length; i++) {
        sBuilder.Append(arr[i].ToString("x2"));
    }

    return sBuilder.ToString();
}    

public void Encrypt(string toEncrypt, bool useHashing) {
    byte[] keyArray;
    byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);

    string key = EncryptKey;

    if (useHashing) {
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));

        hashmd5.Clear();
    } else
        keyArray = UTF8Encoding.UTF8.GetBytes(key);

    Console.WriteLine("hexadecimal key: " + getHexStringFromArray(keyArray));

    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = keyArray;
    tdes.Mode = CipherMode.ECB;
    tdes.Padding = PaddingMode.PKCS7;

    ICryptoTransform cTransform = tdes.CreateEncryptor();
    byte[] resultArray =
        cTransform.TransformFinalBlock(toEncryptArray, 0,
            toEncryptArray.Length);

    tdes.Clear();

    Console.WriteLine("hexadecimal encrypted: " + getHexStringFromArray(resultArray));

    //Return the encrypted data into unreadable string format
    string test = Convert.ToBase64String(resultArray, 0, resultArray.Length);

    Console.WriteLine("Output: " + test);
}

The output for Encrypt("password", true) is:

hexadecimal key: 5d41402abc4b2a76b9719d911017c592
hexadecimal encrypted: 069c44845e907b346b9d82d1d553f391
Output: BpxEhF6QezRrnYLR1VPzkQ==

Now, the Javascript implementation (please, ignore the global variables):

window.text = "password";
window.key = "hello";
var useHashing = true;

if (useHashing){
    key = CryptoJS.MD5(key).toString();
}

window.options = {
    mode: CryptoJS.mode.ECB, 
    padding: CryptoJS.pad.Pkcs7
};

window.textWordArray = CryptoJS.enc.Utf8.parse(text);
window.keyHex = CryptoJS.enc.Hex.parse(key);

console.log('hexadecimal key: ' + keyHex);

window.encrypted = CryptoJS.TripleDES.encrypt(textWordArray, keyHex, options);

var base64String = encrypted.toString();

console.log('base64: ' + base64String);

window.decrypted = CryptoJS.TripleDES.decrypt( {
    ciphertext: CryptoJS.enc.Base64.parse(base64String)
}, keyHex, options);

console.log('decrypted: ' + decrypted.toString(CryptoJS.enc.Utf8));

Produces this result:

hexadecimal key: 5d41402abc4b2a76b9719d911017c592
base64: BK5f0AhEuUl9pYEy2Mliyw== 

Which is different from the C# implementation.

Here you can find the Javascript code.

Any help?

Upvotes: 2

Views: 7023

Answers (3)

tapos ghosh
tapos ghosh

Reputation: 2202

var message = "information";

var key = "t8g5av9Z0IsZ77tyox9H19Rb"; //length=22
var iv  = "OjgLqBur"; //length=22

let cipher = CryptoJS.TripleDES.encrypt(message, CryptoJS.enc.Utf8.parse(key), {
  iv: CryptoJS.enc.Utf8.parse(iv),
  mode: CryptoJS.mode.CBC
});
let decrypt = CryptoJS.TripleDES.decrypt(cipher, CryptoJS.enc.Utf8.parse(key), {
  iv: CryptoJS.enc.Utf8.parse(iv)
});

console.log(cipher.toString());
console.log(decrypt.toString(CryptoJS.enc.Utf8));

Upvotes: 0

Sanket Mehta
Sanket Mehta

Reputation: 78

Here is Decrypter using 3DES-ECB of Forge js. Since I couldn't find forge js solution adding one so others can use it.

var md = forge.md.md5.create();
md.update(window.key);

var key = md.digest().getBytes();
//3DES-ECB requires 24byte of data and key returned from md5 is 16byte
var k1 = key.substring(0, 8);
var key1 = key + key1;

var input = forge.util.createBuffer(forge.util.decode64(window.text));
var decTer = forge.cipher.createDecipher('3DES-ECB', key1);
decTer.start();
decTer.update(input);

return decTer.output.getBytes();

Upvotes: 0

Khang Tran
Khang Tran

Reputation: 96

TripleDES requires 24-byte key (k1 + k2 + k3). Your key is only 16-byte. And .NET auto completes with k3 = k1. But Javascript does not, k3 = 0. Please modify the key:

if (useHashing){
   key = CryptoJS.MD5(key).toString();
   var k1 = key.substring(0, 16);
   key = key + k1;
}

Upvotes: 8

Related Questions