简体   繁体   English

如何将 CryptoJS 解密代码转换为 C#?

[英]How to convert CryptoJS decryption code into C#?

I have this code in CryptoJS, inside browser:我在浏览器内的 CryptoJS 中有这段代码:

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. cipherText也来自我无法访问的另一台服务器。 However, I have access to key and to iv .但是,我可以访问keyiv

I can decrypt that cipherText inside a browser's console.我可以在浏览器的控制台中解密该cipherText But I want to use these keys to decrypt that cipherText inside C# code.但我想使用这些密钥来解密cipherText代码中的密文。 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.我不明白我是否正确地从十六进制解码给定的cipherText Also I can't instantiate Rfc2898DeriveBytes , because I don't know what the second parameter (salt) should be.我也无法实例化Rfc2898DeriveBytes ,因为我不知道第二个参数(盐)应该是什么。

Also I don't know where should I use that iv I've gotten from the CryptoJS code.另外,我不知道应该在哪里使用我从 CryptoJS 代码中获得的iv

Could you please help?能否请你帮忙?

So that both codes are compatible, the following changes of the C# code are necessary:为了使两个代码兼容,需要对 C# 代码进行以下更改:

  • The return type of the Decrypt method must be changed from void to string . Decrypt方法的返回类型必须从void更改为string
  • Key and IV have to be decoded hexadecimal like the ciphertext with FromHexString . Key 和 IV 必须像FromHexString的密文一样被解码为十六进制。
  • Instead of AES, TripleDES must be used.必须使用TripleDES而不是 AES。
  • Rfc2898DeriveBytes implements PBKDF2 and must not be applied (since the JavaScript code does not use PBKDF2 either). Rfc2898DeriveBytes实现PBKDF2且不得应用(因为 JavaScript 代码也不使用 PBKDF2)。
  • The decrypted data must not be decoded with Encoding.Unicode (which corresponds to UTF16LE in .NET), but with Encoding.UTF8 .解密后的数据不能使用Encoding.Unicode (对应于 .NET 中的 UTF16LE)进行解码,而是使用Encoding.UTF8进行解码。

The C# code can handle 24 bytes keys (to support 3TDEA ) and 16 bytes keys (to support the less secure 2TDEA ). C# 代码可以处理 24 字节密钥(以支持3TDEA )和 16 字节密钥(以支持不太安全的2TDEA )。 The posted CryptoJS code also handles these key sizes plus additionally 8 bytes keys (to support the least secure, DES compatible variant 1TDEA ).发布的 CryptoJS 代码还处理这些密钥大小以及额外的 8 字节密钥(以支持最不安全的 DES 兼容变体1TDEA )。

The following C# code decrypts a ciphertext generated with CryptoJS and 3TDEA :以下 C# 代码解密使用 CryptoJS 和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.也可以使用发布的 JavaScript 代码进行解密,该代码显示了两种代码的功能等效性。

Note: Since AES is more performant than TripleDES, AES should be used if possible .注意:由于 AES 比 TripleDES 性能更高,因此应尽可能使用 AES。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM