尝试在node.js中获取AESencryptionstring以匹配.net中的encryption值

我试图encryptionnode.js中的一个值,我可以在.net中解密。 我已经给他们的代码,在事物的.net方面用于encryption值,我试图在我的node.js脚本中实现相同的encryption值。

我绝对不是一个encryption爱好者,所以请帮我弄清楚我哪里出错了。 我的node.jsencryption值与.netencryption值不匹配,而且我的node.jsencryption值实际上每次运行脚本时都不会返回相同的值。

这是.netencryption逻辑:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; using System.IO; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("start:"); string key = "mysecretkey"; string secret = "encryptThisMessage"; string crypto = EncryptString(secret, key); Console.WriteLine(crypto); string returnValue = DecryptString(crypto, key); Console.WriteLine(returnValue); Console.ReadKey(); } /// <summary> /// Encrpyts the sourceString, returns this result as an Aes encrpyted, BASE64 encoded string /// </summary> /// <param name="plainSourceStringToEncrypt">a plain, Framework string (ASCII, null terminated)</param> /// <param name="passPhrase">The pass phrase.</param> /// <returns> /// returns an Aes encrypted, BASE64 encoded string /// </returns> public static string EncryptString(string plainSourceStringToEncrypt, string passPhrase) { //Set up the encryption objects using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passPhrase))) { byte[] sourceBytes = Encoding.ASCII.GetBytes(plainSourceStringToEncrypt); ICryptoTransform ictE = acsp.CreateEncryptor(); //Set up stream to contain the encryption MemoryStream msS = new MemoryStream(); //Perform the encrpytion, storing output into the stream CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write); csS.Write(sourceBytes, 0, sourceBytes.Length); csS.FlushFinalBlock(); //sourceBytes are now encrypted as an array of secure bytes byte[] encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer //return the encrypted bytes as a BASE64 encoded string return Convert.ToBase64String(encryptedBytes); } } /// <summary> /// Decrypts a BASE64 encoded string of encrypted data, returns a plain string /// </summary> /// <param name="base64StringToDecrypt">an Aes encrypted AND base64 encoded string</param> /// <param name="passphrase">The passphrase.</param> /// <returns>returns a plain string</returns> public static string DecryptString(string base64StringToDecrypt, string passphrase) { //Set up the encryption objects using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passphrase))) { byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt); ICryptoTransform ictD = acsp.CreateDecryptor(); //RawBytes now contains original byte array, still in Encrypted state //Decrypt into stream MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length); CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read); //csD now contains original byte array, fully decrypted //return the content of msD as a regular string return (new StreamReader(csD)).ReadToEnd(); } } private static AesCryptoServiceProvider GetProvider(byte[] key) { AesCryptoServiceProvider result = new AesCryptoServiceProvider(); result.BlockSize = 128; result.KeySize = 128; result.Mode = CipherMode.CBC; result.Padding = PaddingMode.PKCS7; result.GenerateIV(); result.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; byte[] RealKey = GetKey(key, result); result.Key = RealKey; // result.IV = RealKey; return result; } private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p) { byte[] kRaw = suggestedKey; List<byte> kList = new List<byte>(); for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8) { kList.Add(kRaw[(i / 8) % kRaw.Length]); } byte[] k = kList.ToArray(); return k; } } } 

我的node.js脚本:

 var crypto = require('crypto-js'); var key = "mysecretkey"; var secret = "encryptThisMessage"; e1 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7}); e2 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7}); console.log('e1'); console.log(crypto.enc.Hex.stringify(e1)); console.log(e1.toString()); console.log(e1.salt.toString()); console.log(e1.iv.toString()); console.log(e1.ciphertext.toString()); console.log(e1.ciphertext.toString(crypto.enc.Base64)); console.log('e2'); console.log(e2.toString()); console.log(e2.salt.toString()); console.log(e2.iv.toString()); console.log(e2.ciphertext.toString(crypto.enc.Base64)); 

在c#代码中运行encryption段时,值如下所示:(出于安全目的稍作修改) dp+8cjr/ajEw5oePdiG+4g==我怎样才能改变我的node.js代码来输出这个匹配的encryption值?

node.js脚本的输出:

在这里输入图像说明

你正在混合苹果和橘子

当你传递一个string作为CryptoJS的关键字时 ,它会派生出一个密钥和iv来用于解密。 该string被视为一个密码 ,这是盐碱 。 在node.js中运行这个代码几次:

 var key = "mysecretkey"; var secret = "encryptThisMessage"; e1 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7}); console.log("key: " + crypto.enc.Base64.stringify(e1.key)); console.log("iv: " + crypto.enc.Base64.stringify(e1.iv)); console.log("salt: " + crypto.enc.Base64.stringify(e1.salt)); console.log("ciphertext: " + crypto.enc.Base64.stringify(e1.ciphertext)); p = crypto.AES.decrypt(e1, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7}); console.log("decrypted: " + crypto.enc.Utf8.stringify(p)); 

注意它每次产生不同的密钥和IV,但它总是解密回原来的(因为e1携带解密的盐派生出相同的密钥)。 在这里查看CryptoJS的这个文档。

在你的C#代码中 ,你总是使用相同的密钥和IV 。 这些与CryptoJS 的密钥和IV 不匹配 。 试试这个代码与你的C#代码产生的密钥和IV完全匹配:

 var key = crypto.enc.Base64.parse('bXlzZWNyZXRrZXlteXNlYw=='); // Matching C# code's key var iv = crypto.enc.Base64.parse('AAAAAAAAAAAAAAAAAAAAAA=='); // 16 ZERO bytes, same as C# code var secret = "encryptThisMessage"; e1 = crypto.AES.encrypt(secret, key, {iv: iv, mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7}); console.log("ciphertext: " + crypto.enc.Base64.stringify(e1.ciphertext)); 

请注意,这次我没有将CryptoJS传递给密钥的string,而是将其解释为密码,而是将CryptoJS 字数组 直接解释为密钥字节 。 另外,我正在通过IV的参数。

最后一点代码产生与C#代码相同的密文。 我在这里使用Base64作为键和IV作为创build字数组的方便快捷键。 在两端使用相同的密钥和IV ,它将工作。

编辑:

我认为有趣的是显示CryptoJS – 即OpenSSL – 代码中的密钥派生,以便代替CryptoJS匹配C#,使C#与CryptoJS匹配。

这里描述OpenSSL密钥派生

这导出了关键和IV – 保持简单明了:

 public byte[] Derive48(string passphrase, byte[] salt) { using (var md5 = new MD5CryptoServiceProvider()) { var source = Encoding.UTF8.GetBytes(passphrase).Concat(salt).ToArray(); var data = md5.ComputeHash(source); var output = data; while (output.Length < 48) { data = md5.ComputeHash(data.Concat(source).ToArray()); output = output.Concat(data).ToArray(); } return output.Take(48).ToArray(); } } 

你可以像这样使用它:

 string key = "mysecretkey"; string secret = "encryptThisMessage"; byte[] salt = Convert.FromBase64String("zTEeMVPN2eY="); string crypto = EncryptString(secret, key, salt); Console.WriteLine(crypto); string returnValue = DecryptString(crypto, key, salt); Console.WriteLine(returnValue); 

 public string EncryptString(string plainSourceStringToEncrypt, string passPhrase, byte[] salt) { //Set up the encryption objects using (AesCryptoServiceProvider acsp = GetProvider(passPhrase, salt)) { 

 private AesCryptoServiceProvider GetProvider(string passphrase, byte[] salt) { AesCryptoServiceProvider result = new AesCryptoServiceProvider(); result.BlockSize = 128; result.KeySize = 128; result.Mode = CipherMode.CBC; result.Padding = PaddingMode.PKCS7; var derived = this.Derive48(passphrase, salt); result.Key = derived.Take(32).ToArray(); result.IV = derived.Skip(32).Take(16).ToArray(); return result; }