2

I do not get the same result on CryptoJS. May you please check what is wrong?

Here is my expected input/outputs:

Encrypted String: 723024D59CF7801A295F81B9D5BB616E
Decrypted String: stackoverflow

Here are my Decryption/Encryption methods in C# . Encryption is TripleDES mode CBC, I am using the same key and iv on the CryptoJS code.

public static string Encrypt(string data, string key, string iv)
{
    byte[] bdata = Encoding.ASCII.GetBytes(data);
    byte[] bkey = HexToBytes(key);
    byte[] biv = HexToBytes(iv);

    var stream = new MemoryStream();
    var encStream = new CryptoStream(stream,
        des3.CreateEncryptor(bkey, biv), CryptoStreamMode.Write);

    encStream.Write(bdata, 0, bdata.Length);
    encStream.FlushFinalBlock();
    encStream.Close();

    return BytesToHex(stream.ToArray());
}

public static string Decrypt(string data, string key, string iv)
{
    byte[] bdata = HexToBytes(data);
    byte[] bkey = HexToBytes(key);
    byte[] biv = HexToBytes(iv);

    var stream = new MemoryStream();
    var encStream = new CryptoStream(stream,
        des3.CreateDecryptor(bkey, biv), CryptoStreamMode.Write);

    encStream.Write(bdata, 0, bdata.Length);
    encStream.FlushFinalBlock();
    encStream.Close();

    return Encoding.ASCII.GetString(stream.ToArray());
}

Here is how I do the decryption using CryptoJS

var key = "90033E3984CEF5A659C44BBB47299B4208374FB5DC495C96";
var iv = "E6B9AFA7A282A0CA";

key = CryptoJS.enc.Hex.parse(key);
iv = CryptoJS.enc.Hex.parse(iv);


// Input is a Hex String
var decrypted = CryptoJS.TripleDES.decrypt('723024D59CF7801A295F81B9D5BB616E', key, { iv : iv, mode:CryptoJS.mode.CBC});
console.log(decrypted.toString());
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
bman
  • 3,740
  • 9
  • 34
  • 40
  • hi, can you give me HexToBytes function. Also what is des3 object ? Can you me these function in standalone form. I have to do same thing but I am new for encryption part. – Sagar Dec 01 '17 at 08:03

2 Answers2

3

CryptoJS expects the ciphertext to be a CipherParams object or an OpenSSL-encoded string. You've passed in the ciphertext as Hex. Do this instead:

var decrypted = CryptoJS.TripleDES.decrypt({
    ciphertext: CryptoJS.enc.Hex.parse('723024D59CF7801A295F81B9D5BB616E')
}, key, { 
    iv : iv, 
    mode:CryptoJS.mode.CBC
});

decrypted is now a WordArray object. Stringifying it leads to a string with the default encoding which is Hex. If you know that you should get text out, you can use the appropriate encoding like:

console.log(decrypted.toString(CryptoJS.enc.Utf8));
Artjom B.
  • 61,146
  • 24
  • 125
  • 222
2

The answer by Artjom B works, but is problematic if used with a static IV. The IV (and SALT) should change from message to message. And trying to create and send non-static IV / SALTS between different languages/libraries can be difficult.

So, as I was struggling also with exchanging encrypted texts between C# and JS I took the time to solve that once and for all and wrote a small library and published it under the MIT license for everyone to use.

The ciphertext is in base64 and combined by ":" with the base64-SALT and the base64-IV

These are the steps to use it:

Use the library from https://github.com/smartinmedia/Net-Core-JS-Encryption-Decryption

For C#:

    //Encrypt plain text in C# with a random password
    string plainText = "This is my secret text!";
    //You can also use the built in password generator!!
    //string passPhrase = PasswordGenerator.GenerateRandomPassword(20);
    //Or use your own password:        
    string passPhrase = "This_is_my_password!";

    var enc = EncryptionHandler.Encrypt(plainText, passPhrase);
    Console.WriteLine("Plaintext: 'This is my secret text' with password 'This_is_my_password!' results in ciphertext: " + enc);

    var dec3 = EncryptionHandler.Decrypt(enc, passPhrase);
    Console.WriteLine("And decrypting again: " + dec3);
    Console.WriteLine("Please start the index.html to see the same in Javascript. Encryption / Decryption run in both ways and can be interchanged between C# and JS!");

For JS:

// This is the ciphertext, which was encrypted by C# to check the interchangeability:
    var encryptedBase64FromCSharp = "uTkXNB+PSTjzwUCJbfAHVHd95YOlcJr38wbF08ZxqNw=:PNGRjWb5tOINneaVVf8+cw==:Aic+gosvLjTrCebzY8l/usTh+kWuE0v1xSWw7apYunI=";
    var passPhrase = "This_is_my_password!";

    var eH = new encryptionHandler();

    var decryptedFromCSharp = eH.decrypt(encryptedBase64FromCSharp, passPhrase);

    //Now encrypt again with JS
    var encryptTextWithJs = eH.encrypt(decryptedFromCSharp, "This_is_my_password!");
    //And decrypt again with JS
    var decryptedTextWithJs = eH.decrypt(encryptTextWithJs, "This_is_my_password!");

So, as you can see here, the ciphertexts can be exchanged between C# and JS with randomly generated SALTs and IVs (which are generated in the methods encrypt/decrypt).

  • I have a case where I have to execute third party JS library function by passing API Key (Actual Key) from that provider. Do you think I can use your idea ? Because my assumption is like, if someone figure out that you are passing encyrpted text same as above way then anyone can decrypt text using same JS code from answer. Please correct me if I understood something wrong – Jigar Sangoi May 13 '21 at 16:19
  • You should never do "encryption by obfuscation" - in fact the above example depends on the strength of your password. So, if you use the AES algorithm (which it uses), then it depends on keeping the password secret. I don't really understand you use case well enough, but if you want to you can contact me through our website smartinmedia.com – Martin Weihrauch May 17 '21 at 14:05
  • I still don't get the "keeping the password secret"... I mean, I get ofc, but how can I make it secret? Because, if I generate a random password in JS, encrypt a text and send it to C# to be decrypted, C# will have to know this password, right? How to share that? In the body of a POST request? If so, then every request to be decrypted I will need to send the password from JS to C#, right? – André Miranda Dec 21 '22 at 13:27