如何在 Angular 9 中使用 CryptoJS 来获得与 C# Rfc2898DeriveBytes 相同的加密字符串
How to use CryptoJS in Angular 9 to get same encrypted string like C# Rfc2898DeriveBytes
我正在尝试使用 CryptoJS 将以下 C# 代码转换为 angular 9,因为当我尝试将 C# 代码转换为 angular 时,它会给出不同的加密字符串。
如何使用 CryptoJS 将使用 Rfc2898DeriveBytes 的 C# 代码转换为 angular 9?
C#代码:
public static string Encrypt(string clearText)
{
clearText = '123456';
let EncryptionKey:any = "secret key string";
let clearBytes :any= Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
Angular 9码:
import * as CryptoJS from 'crypto-js';
encryptionKey: any = 'secret key string';
let encryptedStr = CryptoJS.AES.encrypt('123456', this.encryptionKey.trim()).toString();
任何人都可以帮助我使用 angular 9 获得与 C# 相同的加密吗?
好吧,我知道它可能在 Whosebug 上不受欢迎,因为 it is not a code-writing service
但我发现这个挑战是一项很好的运动,所以这里是:
let clearText = '123456';
let encryptionKey = CryptoJS.enc.Utf8.parse('secret key string');
let salt = CryptoJS.enc.Base64.parse('SXZhbiBNZWR2ZWRldg=='); // this is the byte array in .net fiddle
let iterations = 1000; // https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes?view=netcore-3.1
let keyAndIv = CryptoJS.PBKDF2(encryptionKey, salt, { keySize: 256/32 + 128/32, iterations: iterations, hasher: CryptoJS.algo.SHA1 }); // so PBKDF2 in CryptoJS is direct in that it
// always begins at the beginning of the password, whereas the .net
// implementation offsets by the last length each time .GetBytes() is called
// so we had to generate a Iv + Salt password and then split it
let hexKeyAndIv = CryptoJS.enc.Hex.stringify(keyAndIv);
let key = CryptoJS.enc.Hex.parse(hexKeyAndIv.substring(0, 64));
let iv = CryptoJS.enc.Hex.parse(hexKeyAndIv.substring(64, hexKeyAndIv.length));
// As you're using Encoding.Unicde in .net, we have to use CryptoJS.enc.Utf16LE here.
let encryptedStr = CryptoJS.AES.encrypt(CryptoJS.enc.Utf16LE.parse(clearText), key, {iv: iv}).toString();
console.log(encryptedStr)
JSFiddle:https://jsfiddle.net/nhupdk6q/1/
这是我在 .Net fiddle 中使用的相应代码(遗憾的是不允许 'save' 不登录),我使用 .Net Core 3.1 运行时 System.Security.Cryptography.Algorithms
nuget 包。
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var clearText = "123456";
var EncryptionKey = "secret key string";
var clearBytes = Encoding.Unicode.GetBytes(clearText);
using (System.Security.Cryptography.Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
Console.WriteLine(clearText);
}
}
两个列表打印相同的字符串。
最大的挑战,如评论中所述,是因为您的 .Net 代码重复使用相同的 PBKDF2 实例,每个 .GetBytes()
调用本质上是密码的下一个 cb
。 (cb是.net代码中的参数名https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.getbytes?view=netcore-3.1#System_Security_Cryptography_Rfc2898DeriveBytes_GetBytes_System_Int32_)
CryptoJS中的PBKDF2没有这个,所以我们需要调用一次,得到Key和Iv,然后自己解析。
我正在尝试使用 CryptoJS 将以下 C# 代码转换为 angular 9,因为当我尝试将 C# 代码转换为 angular 时,它会给出不同的加密字符串。
如何使用 CryptoJS 将使用 Rfc2898DeriveBytes 的 C# 代码转换为 angular 9?
C#代码:
public static string Encrypt(string clearText)
{
clearText = '123456';
let EncryptionKey:any = "secret key string";
let clearBytes :any= Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
return clearText;
}
Angular 9码:
import * as CryptoJS from 'crypto-js';
encryptionKey: any = 'secret key string';
let encryptedStr = CryptoJS.AES.encrypt('123456', this.encryptionKey.trim()).toString();
任何人都可以帮助我使用 angular 9 获得与 C# 相同的加密吗?
好吧,我知道它可能在 Whosebug 上不受欢迎,因为 it is not a code-writing service
但我发现这个挑战是一项很好的运动,所以这里是:
let clearText = '123456';
let encryptionKey = CryptoJS.enc.Utf8.parse('secret key string');
let salt = CryptoJS.enc.Base64.parse('SXZhbiBNZWR2ZWRldg=='); // this is the byte array in .net fiddle
let iterations = 1000; // https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes?view=netcore-3.1
let keyAndIv = CryptoJS.PBKDF2(encryptionKey, salt, { keySize: 256/32 + 128/32, iterations: iterations, hasher: CryptoJS.algo.SHA1 }); // so PBKDF2 in CryptoJS is direct in that it
// always begins at the beginning of the password, whereas the .net
// implementation offsets by the last length each time .GetBytes() is called
// so we had to generate a Iv + Salt password and then split it
let hexKeyAndIv = CryptoJS.enc.Hex.stringify(keyAndIv);
let key = CryptoJS.enc.Hex.parse(hexKeyAndIv.substring(0, 64));
let iv = CryptoJS.enc.Hex.parse(hexKeyAndIv.substring(64, hexKeyAndIv.length));
// As you're using Encoding.Unicde in .net, we have to use CryptoJS.enc.Utf16LE here.
let encryptedStr = CryptoJS.AES.encrypt(CryptoJS.enc.Utf16LE.parse(clearText), key, {iv: iv}).toString();
console.log(encryptedStr)
JSFiddle:https://jsfiddle.net/nhupdk6q/1/
这是我在 .Net fiddle 中使用的相应代码(遗憾的是不允许 'save' 不登录),我使用 .Net Core 3.1 运行时 System.Security.Cryptography.Algorithms
nuget 包。
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
var clearText = "123456";
var EncryptionKey = "secret key string";
var clearBytes = Encoding.Unicode.GetBytes(clearText);
using (System.Security.Cryptography.Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
}
clearText = Convert.ToBase64String(ms.ToArray());
}
}
Console.WriteLine(clearText);
}
}
两个列表打印相同的字符串。
最大的挑战,如评论中所述,是因为您的 .Net 代码重复使用相同的 PBKDF2 实例,每个 .GetBytes()
调用本质上是密码的下一个 cb
。 (cb是.net代码中的参数名https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.rfc2898derivebytes.getbytes?view=netcore-3.1#System_Security_Cryptography_Rfc2898DeriveBytes_GetBytes_System_Int32_)
CryptoJS中的PBKDF2没有这个,所以我们需要调用一次,得到Key和Iv,然后自己解析。