求助:将CryptoJS.AES.decrypt的JavaScript代码转为C#实现
解决CryptoJS AES解密的C#实现问题
你的JavaScript代码依赖CryptoJS的默认AES解密逻辑,它处理的是OpenSSL格式的加密数据(开头U2FsdGVkX1对应Base64解码后的Salted__标识)。以下是完全匹配该逻辑的C#实现:
核心逻辑说明
CryptoJS使用密码而非直接密钥时,会执行以下步骤:
- 从密文开头提取8字节盐值(前8字节为固定标识
Salted__,后续8字节是实际盐) - 通过PBKDF2算法,以密码、盐为输入,生成32字节AES密钥和16字节IV(默认迭代次数1000,哈希算法SHA-1)
- 使用AES-CBC模式、PKCS7填充解密剩余密文
完整C#代码
using System; using System.IO; using System.Security.Cryptography; using System.Text; public class AesDecryptor { public static string Decrypt(string ciphertextBase64, string password) { // 解码Base64密文 byte[] ciphertextBytes = Convert.FromBase64String(ciphertextBase64); // 提取盐和实际加密数据:前8字节是"Salted__",接下来8字节是盐,剩余是加密内容 byte[] salt = new byte[8]; Array.Copy(ciphertextBytes, 8, salt, 0, 8); byte[] encryptedData = new byte[ciphertextBytes.Length - 16]; Array.Copy(ciphertextBytes, 16, encryptedData, 0, encryptedData.Length); // 用PBKDF2生成密钥和IV byte[] passwordBytes = Encoding.UTF8.GetBytes(password); byte[] keyAndIv = GenerateKeyAndIv(passwordBytes, salt); byte[] key = new byte[32]; byte[] iv = new byte[16]; Array.Copy(keyAndIv, 0, key, 0, 32); Array.Copy(keyAndIv, 32, iv, 0, 16); // AES-CBC解密 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 msDecrypt = new MemoryStream(encryptedData)) using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) using (StreamReader srDecrypt = new StreamReader(csDecrypt)) { return srDecrypt.ReadToEnd(); } } } private static byte[] GenerateKeyAndIv(byte[] password, byte[] salt) { // 匹配CryptoJS默认PBKDF2参数:1000次迭代,SHA-1哈希,生成48字节(32位密钥+16位IV) using (Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, salt, 1000, HashAlgorithmName.SHA1)) { return pbkdf2.GetBytes(48); } } // 测试示例 public static void Main() { string ciphertext = "U2FsdGVkX1+pmKonC+E+MGs9BltH/axDE3IRYIV+vHF0yuteP4JAzuQ/CmmSgY2xkqeAhl02bIL5cJhsE1NOsc79ENadltxt2QEBymquSnbUsuhtxHptgGUXV0XuSPPQAt4/Rk2bDaR7qJw2LJKh4U1/pqeJUlqP2qLdtBTLs7E+W2TVh0/yMAVyuGUctEtx41qOClFzyfPxNydtSO6vzQ+3OOrI4Ov7ZgX07OJIF5sAq+m3pJQspL93UHbKS1w7a4dJUn2s+7JRYASkD9IBsheXI//SiE3yJv3c/dOs3VFDl4ok+m0MkgMwHQ0ELySUx1/UVTY6lefenO2RgASE52ATwIyKy7rdf4GKnrYpU7rdMZwcu1enI8Jpz5Ri3pFioyJSiPPDVKIecDQJ+UsQpsszWA6mQb3YMRhIxJrdcjSGEIHPGTHFEYgVpSO9y4EeGKLvX5oJ0tQDhO+QW1LQszcojRsgFuyFkdAsjNVzRNK3K4qE6Ua8j6t/kyE9i/MW7DQ0nT3d3CozLGS68PdEI34kljArY6Hmrgkt4InvBKdMvfffogKE3NtwBhf/3nK5"; string password = "F2Gs3zjSjd3"; string result = Decrypt(ciphertext, password); Console.WriteLine(result); } }
关键注意事项
- 必须严格解析OpenSSL格式的密文结构,不能直接解密整个Base64数据
- 完全匹配CryptoJS的PBKDF2参数,否则生成的密钥/IV会不一致
- AES模式和填充方式必须用CBC+PKCS7,这是CryptoJS的默认配置
内容的提问来源于stack exchange,提问作者Raúl Gavilanes Lara
相关产品推荐
相关产品推荐

