Reputation: 7237
I have this code in CryptoJS, inside browser:
var decrypt = function (cipherText) {
var key = "a_long_key_goes_here";
var iv = "initial_vector_goes_here";
key = CryptoJS.enc.Hex.parse(key);
iv = CryptoJS.enc.Hex.parse(iv);
var decrypted = CryptoJS.TripleDES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse(cipherText)
}, key, {
iv: iv,
mode: CryptoJS.mode.CBC
});
var clearText = decrypted.toString(CryptoJS.enc.Utf8);
return clearText;
};
This code is not written by me. Also the cipherText
come from another server that I have no access to. However, I have access to key
and to iv
.
I can decrypt that cipherText
inside a browser's console. But I want to use these keys to decrypt that cipherText
inside C# code. Here's the code I've written:
public void Desrypt()
{
ICryptoTransform decryptor;
UTF8Encoding encoder;
string key = "a_long_key_goes_here";
string iv = "initial_vector_goes_here";
var cipherText = "cipher_text_goes_here";
string clearText = "";
byte[] cipherBytes = FromHexString(cipherText);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { });
aes.Key = pdb.GetBytes(32);
aes.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
clearText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return clearText;
}
public static byte[] FromHexString(string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return bytes;
}
I have some problems though. I don't understand if I'm correctly decoding the given cipherText
from hexadecimal or not. Also I can't instantiate Rfc2898DeriveBytes
, because I don't know what the second parameter (salt) should be.
Also I don't know where should I use that iv
I've gotten from the CryptoJS code.
Could you please help?
Upvotes: 1
Views: 176
Reputation: 49525
So that both codes are compatible, the following changes of the C# code are necessary:
Decrypt
method must be changed from void
to string
.FromHexString
.Rfc2898DeriveBytes
implements PBKDF2 and must not be applied (since the JavaScript code does not use PBKDF2 either).Encoding.Unicode
(which corresponds to UTF16LE in .NET), but with Encoding.UTF8
.The C# code can handle 24 bytes keys (to support 3TDEA) and 16 bytes keys (to support the less secure 2TDEA). The posted CryptoJS code also handles these key sizes plus additionally 8 bytes keys (to support the least secure, DES compatible variant 1TDEA).
The following C# code decrypts a ciphertext generated with CryptoJS and 3TDEA:
public string Decrypt()
{
byte[] key = FromHexString("000102030405060708090a0b0c0d0e0f1011121314151617"); // 24 bytes (3TDEA)
byte[] iv = FromHexString("0001020304050607"); // 8 bytes
byte[] ciphertext = FromHexString("2116057c372e0e95dbe91fbfd148371b8e9974187b71e7c018de89c757280ad342d4191d29472040ee70d19015b025e1");
string plaintext = "";
using (TripleDES tdes = TripleDES.Create())
{
tdes.Key = key;
tdes.IV = iv;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor(tdes.Key, tdes.IV), CryptoStreamMode.Write))
{
cs.Write(ciphertext, 0, ciphertext.Length);
}
plaintext = Encoding.UTF8.GetString(ms.ToArray());
}
}
return plaintext;
}
The decryption is also possible with the posted JavaScript code, which shows the functional equivalence of both codes.
Note: Since AES is more performant than TripleDES, AES should be used if possible.
Upvotes: 2