【发布时间】:2014-08-20 23:06:30
【问题描述】:
我正在尝试加密 node.js 中的一个值,我可以在 .net 中解密该值。我已经获得了他们在 .net 方面用于加密值的代码,我正在尝试在我的 node.js 脚本中实现相同的加密值。
我绝对不是加密爱好者,所以请帮我弄清楚我哪里出错了。我的 node.js 加密值与 .net 加密值不匹配,我的 node.js 加密值实际上也不是每次运行脚本时都返回相同的值。
这是 .net 加密逻辑:
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# 代码中运行加密部分时,值如下所示:(出于安全目的稍作修改)dp+8cjr/ajEw5oePdiG+4g==。 如何更改我的 node.js 代码以输出此匹配的加密值?
node.js 脚本的输出:
【问题讨论】:
-
您完全缺少 C# 代码中的密钥派生部分。即使明文相同,密文应该看起来是随机的。这可能是由于每次运行使用不同的盐。
-
你能详细说明(也许在答案而不是评论中)?我没有写 c# 部分,也没有完全理解它。
-
尝试以this为起点。
-
那么最终是c#实现有问题,还是只是我没有在node.js版本中使用所有适当的设置/配置?
-
视情况而定,如果要使用密码,请更改 C# 实现。要使用键来实现它,请将显式 IV 添加到 NodeJS 实现中。
标签: c# javascript node.js encryption cryptography