Angular加密数据后,如何在C#服务端实现正确解密?
It looks like your issue stems from mismatched encryption/decryption parameters between CryptoJS and your C# code. Let's break down why this happens and how to fix it:
Why You're Getting Garbled Text
When you use CryptoJS.AES.encrypt("FEAPS8905Q", "myPassword"), CryptoJS doesn't just encrypt the text directly—it generates an OpenSSL-compatible ciphertext string. This string includes:
- A fixed header (
Salted__in bytes, which becomesU2FsdGVkX1in Base64) - A random 8-byte salt
- The actual encrypted data
Your C# code is likely treating the entire Base64 string as raw ciphertext, ignoring the salt and header, and using mismatched key derivation logic (CryptoJS uses PBKDF2 with SHA1, 1000 iterations by default, while C#'s default AES setup doesn't handle this out of the box).
Solution: Update C# Code to Parse CryptoJS's OpenSSL Format
Here's a complete C# method that correctly decodes the CryptoJS-generated ciphertext:
using System; using System.IO; using System.Security.Cryptography; using System.Text; public static class CryptoHelper { public static string DecryptCryptoJSAes(string cipherText, string password) { // Convert Base64 ciphertext to byte array byte[] fullCipherBytes = Convert.FromBase64String(cipherText); // Extract salt (first 8 bytes after the "Salted__" header) byte[] saltBytes = new byte[8]; Array.Copy(fullCipherBytes, 8, saltBytes, 0, 8); // Extract actual encrypted data (after header + salt) byte[] encryptedDataBytes = new byte[fullCipherBytes.Length - 16]; Array.Copy(fullCipherBytes, 16, encryptedDataBytes, 0, encryptedDataBytes.Length); // Derive key and IV using PBKDF2 (matches CryptoJS's default behavior) var pbkdf2 = new Rfc2898DeriveBytes( password, saltBytes, 1000, HashAlgorithmName.SHA1 ); byte[] key = pbkdf2.GetBytes(32); // 256-bit key (CryptoJS default for AES) byte[] iv = pbkdf2.GetBytes(16); // 128-bit IV // Decrypt using AES-CBC with PKCS7 padding using (Aes aes = Aes.Create()) { aes.Key = key; aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) using (MemoryStream ms = new MemoryStream(encryptedDataBytes)) using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) using (StreamReader sr = new StreamReader(cs, Encoding.UTF8)) { return sr.ReadToEnd(); } } } }
How to Use It
Call the method with your ciphertext and password:
string originalText = CryptoHelper.DecryptCryptoJSAes( "U2FsdGVkX19mi5mXlJ14Lj0XcJBbqMPDzi/UeNXK4Cw=", "myPassword" ); // originalText will be "FEAPS8905Q"
Alternative: Match CryptoJS to C#'s Default Parameters (Less Secure)
If you prefer to adjust your Angular code instead, you can force CryptoJS to use fixed key/IV values that match C#'s default AES setup. However, this skips the automatic salt generation (which reduces security), so it's not recommended for production:
// Define fixed key and IV (must match C# exactly) const key = CryptoJS.enc.Utf8.parse('myPassword'); // Ensure key length is 16/24/32 bytes for AES-128/192/256 const iv = CryptoJS.enc.Utf8.parse('1234567890123456'); // 16-byte IV const panno = CryptoJS.AES.encrypt("FEAPS8905Q", key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }).toString();
Then your C# code can decrypt using the same key/IV pair with standard AES logic.
Key Notes to Avoid Future Issues
- Always use UTF-8 encoding on both sides (CryptoJS defaults to this, so ensure C# uses
Encoding.UTF8when reading decrypted data). - CryptoJS's default AES uses CBC mode and PKCS7 padding—make sure your C# code matches these.
- The salt in CryptoJS's output ensures each encryption of the same text produces a different ciphertext, which is critical for security. Stick with method 1 to retain this feature.
内容的提问来源于stack exchange,提问作者Sridhar Paiya

