【发布时间】:2019-09-13 18:54:17
【问题描述】:
我正在尝试在 JavaScript 中重现以下 C# 解密方法。
此方法用于解密短字符串:姓名、地址、电子邮件地址等
感觉非常接近,因为我能够“成功”解密的字符串似乎部分解密了。
例如,一些电子邮件看起来像这样:x"R�Îd¹1gtWÈ2)web@example.com
CSharp
public static readonly byte[] INIT_VECTOR = { 0x00, 0x00, ... };
public static string Decrypt(string cipherText) {
string EncryptionKey = "Some Encryption Key";
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, INIT_VECTOR);
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
JavaScript
import atob from 'atob';
import forge from 'node-forge';
const InitVector = [0x00, ...];
const EncryptionKey = 'Some Encryption Key';
const iv = Buffer.from(InitVector).toString();
const convertBase64StringToUint8Array = input => {
const data = atob(input);
const array = Uint8Array.from(data, b => b.charCodeAt(0));
return array;
};
const decrypt = cipher => {
const cipherArray = convertBase64StringToUint8Array(cipher);
const key = forge.pkcs5.pbkdf2(EncryptionKey, iv, 1000, 32);
const decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({ iv });
decipher.update(forge.util.createBuffer(cipherArray, 'raw'));
const result = decipher.finish();
if (result) {
return decipher.output.data;
} else {
return false;
}
};
【问题讨论】:
-
在 C# 中,默认模式是 CBC。你应该转移IV。在 C# 中,IV 是随机的。在 JS 中全为 0。部分解密表明 IV 不正确,因为它只影响一个块,即第一个块。 注意: 如果没有限制,CBC 是过时的 AES-GCM 身份验证加密模式。 注意 2: 通常 IV 会添加到密文之前。
-
您需要在 JS 中使用与在 C# 中相同的盐。因此,您需要将盐与加密数据一起发送。没关系,盐不需要保密,它只需要是不可预测的。
标签: javascript c# node.js encryption aes