我在浏览器内部的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;
};
此代码不是我编写的。另外,cipherText
来自我无法访问的另一台服务器。但是,我可以访问key
和iv
。
我可以在浏览器的控制台中解密cipherText
。但是我想使用这些密钥来解密C#代码中的cipherText
。这是我编写的代码:
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;
}
不过我有一些问题。我不知道我是否从十六进制正确解码给定的cipherText
。我也无法实例化Rfc2898DeriveBytes
,因为我不知道第二个参数(盐)应该是什么。
而且我也不知道我应该在哪里使用从CryptoJS代码获得的iv
。
您能帮忙吗?
为了使两个代码兼容,必须对C#代码进行以下更改:
Decrypt
方法的返回类型必须从void
更改为string
。FromHexString
的密文一样以十六进制进行解码。Rfc2898DeriveBytes
实现Rfc2898DeriveBytes
,并且不得应用(因为JavaScript代码也不使用PBKDF2)。Encoding.Unicode
进行解码。C#代码可以处理24个字节的密钥(以支持Encoding.Unicode
)和16个字节的密钥(以支持不太安全的Encoding.UTF8
)。发布的CryptoJS代码还处理这些密钥大小以及另外8个字节的密钥(以支持最不安全的DES兼容变体Encoding.UTF8
)。
以下C#代码解密使用CryptoJS和3TDEA生成的密文:
3TDEA
发布的JavaScript代码也可以解密,该代码显示了两个代码的功能等效。
注意:由于AES比TripleDES性能更高,因此应使用AES 如果可能。