我正在我的 Angular 项目上实现 AES 加密,并在我的 dotnet 代码中对其进行解密。 使用 PBKDF2 显式地实现这一点,而不是依赖隐式推导(CryptoJS.AES.encrypt(text, password))。我不明白这究竟是哪里失败了。
在 Angular 端使用 crypto-js 进行加密:
import { Injectable } from '@angular/core';
import * as CryptoJS from 'crypto-js';
@Injectable({
providedIn: 'root',
})
export class CryptoService {
private secretkey = "MyOwnKey";
encrypt(text: string): string {
// random salt for derivation
let keySize = 256;
let salt = CryptoJS.lib.WordArray.random(16);
// well known algorithm to generate key
let key = CryptoJS.PBKDF2(this.secretkey, salt, {
keySize: keySize/32,
iterations: 100
});
// random IV
let iv = CryptoJS.lib.WordArray.random(16);
// specify everything explicitly
let encrypted = CryptoJS.AES.encrypt(text, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
});
// combine everything together in base64 string
let result = CryptoJS.enc.Base64.stringify(salt.concat(iv).concat(encrypted.ciphertext));
return result;
}
}
Dotnet端解密:
public string decrypt(string cipherText)
{
if (string.IsNullOrEmpty(cipherText))
return string.Empty;
try
{
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
// extract salt (first 16 bytes)
byte[] salt = new byte[16];
Array.Copy(cipherBytes, 0, salt, 0, 16);
_logger.LogInformation("salt: {salt}", salt);
// extract iv (next 16 bytes)
byte[] iv = new byte[16];
Array.Copy(cipherBytes, 16, iv, 0, 16);
_logger.LogInformation("iv: {iv}", iv);
// the rest is encrypted data
byte[] encrypted = new byte[cipherBytes.Length - 32];
Array.Copy(cipherBytes, 32, encrypted, 0, cipherBytes.Length - 32);
_logger.LogInformation("encrypted: {encrypted}", encrypted);
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes("MyOwnKey", salt, 100);
encryptor.Key = pdb.GetBytes(32);
encryptor.Padding = PaddingMode.PKCS7;
encryptor.Mode = CipherMode.CBC;
encryptor.IV = iv;
string plaintext;
using (MemoryStream ms = new MemoryStream(encrypted))
{
using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateDecryptor(), CryptoStreamMode.Read))
{
using (var reader = new StreamReader(cs, Encoding.UTF8))
{
plaintext = reader.ReadToEnd();
reader?.Dispose();
}
cs?.Dispose();
}
}
var cbLength = plaintext.Length;
_logger.LogInformation("plaintext Lenght: {cbLength}", cbLength);
return plaintext;
}
}
catch (Exception ex)
{
return "Decryption error: " + ex.Message;
}
}
当我调用此解密方法时,我得到一个空字符串。为什么会这样?
改变:
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes("MyOwnKey", salt, 100);
到
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes("MyOwnKey", salt, 100, HashAlgorithmName.SHA256);