首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用C#密码js解密AES

如何用C#密码js解密AES
EN

Stack Overflow用户
提问于 2022-11-19 16:29:52
回答 1查看 75关注 0票数 2

我正在尝试用C#在后端解密一个用AES加密的值。解密部分将发生在带有角(使用密码js )的前端,问题是我总是得到一个空字符串作为解密的结果。我不知道我做错了什么。我是不是漏掉了某种配置?

用于加密的C#代码如下所示:

代码语言:javascript
复制
//
EncryptAES("XEMFkT92UtR1VJI8kU8XQJALk98GGEFM", "random text to encrypt");

       public static string EncryptAES(string passPhrase, string plainText)
        {
            byte[] iv = Generate256BitsOfRandomEntropy();
            byte[] temp;
            byte[] array;

            using (Aes aes = Aes.Create())
            {
                byte[] salt = Generate256BitsOfRandomEntropy();

                Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(passPhrase, salt, 100);

                aes.Key = pdb.GetBytes(32);
                aes.KeySize = 256;
                aes.Padding = PaddingMode.PKCS7;
                aes.Mode = CipherMode.CBC;
                aes.IV = iv;

                ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

                using (MemoryStream memoryStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream((Stream)memoryStream, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter streamWriter = new StreamWriter((Stream)cryptoStream, Encoding.UTF8))
                        {
                            streamWriter.Write(plainText);
                        }


                        temp = memoryStream.ToArray();
                        array = salt.Concat(iv).Concat(temp).ToArray();
                        
                        cryptoStream.Flush();
                        encryptor.Dispose();
                    }
                }
            }

            return Convert.ToBase64String(array);
        }
代码语言:javascript
复制
//Random byte[] generator
 private static byte[] Generate256BitsOfRandomEntropy()
        {
            var randomBytes = new byte[16];
            using (var rngCsp = new RNGCryptoServiceProvider())
            {
                rngCsp.GetBytes(randomBytes);
            }
            return randomBytes;
        }

the.ts文件中的解密部分是:

代码语言:javascript
复制
//The param "key" will be same as the C# code: XEMFkT92UtR1VJI8kU8XQJALk98GGEFM
//The param "toDecrypt" will the the Base64 returned by the service in C#

 decryptAES(key: string, toDecrypt: string) {

        var data = Buffer.from(toDecrypt, 'base64');
        var salt = data.slice(0, 16); //first 16 bytes to get the salt
        var iv = data.slice(16, 32);// next 16 bytes to get the IV

        const wordArrayIV = CryptoJS.lib.WordArray.create(Array.from(iv));
        const wordArraySalt = CryptoJS.lib.WordArray.create(Array.from(salt))

        var keyPBKDF2 = CryptoJS.PBKDF2(key, wordArraySalt, {
            keySize: 256 / 32,
            iterations: 100
        });

        var decrypted = CryptoJS.AES.decrypt(toDecrypt, keyPBKDF2, 
            {   
                mode: CryptoJS.mode.CBC, 
                padding: CryptoJS.pad.Pkcs7, 
                iv: wordArrayIV
            });

//Return empty string 
        return decrypted.toString();
    }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-19 18:50:16

在C#代码中,不使用PBKDF2派生的密钥,而是使用随机生成的密钥。这是因为在设置密钥大小时,将隐式地生成一个新键。

因为fix只需删除键大小的设置,即行aes.KeySize = 256 (键大小是在设置键时隐式设置的)。

代码语言:javascript
复制
...
aes.Key = pdb.GetBytes(32);
//aes.KeySize = 256;                // Fix: remove
//aes.Padding = PaddingMode.PKCS7;  // default
//aes.Mode = CipherMode.CBC;        // default
aes.IV = iv;
...

此外,CryptoJS代码中还有几个问题:首先,缓冲区被错误地转换为WordArrays,因此IV和salt是错误的。

此外,密文在分离时没有被考虑,而且还被错误地传递给AES.decrypt()

并且解密的数据是十六进制编码的,但应该被UTF-8解码.

代码语言:javascript
复制
function decryptAES(key, toDecrypt) {
    var data = CryptoJS.enc.Base64.parse(toDecrypt);
    var wordArraySalt = CryptoJS.lib.WordArray.create(data.words.slice(0, 4)); // Fix: Array -> WordArray conversion 
    var wordArrayIV = CryptoJS.lib.WordArray.create(data.words.slice(4, 8)); // Fix: Array -> WordArray conversion
    var wordArrayCt = CryptoJS.lib.WordArray.create(data.words.slice(8)); // Fix: Consider ciphertext
    var keyPBKDF2 = CryptoJS.PBKDF2(key, wordArraySalt, {keySize: 256 / 32, iterations: 100});
    var decrypted = CryptoJS.AES.decrypt({ciphertext: wordArrayCt}, keyPBKDF2, {iv: wordArrayIV}); // Fix: Pass ciphertext as CipherParams object
    return decrypted.toString(CryptoJS.enc.Utf8); // Fix: UTF-8 decode
}

var decrypted = decryptAES('XEMFkT92UtR1VJI8kU8XQJALk98GGEFM', '4YI4unJecVXvvNQVgBsdUwrr7rlwcImDb7t1LT88UO0w8BdFpOp5PLsu6PRJ+eCeKB01rWdVVrGMLj7tOi3KHg==');
console.log(decrypted);
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script>

请注意,上述代码中的密文是用固定的C#代码生成的。

关于漏洞:使用PBKDF2进行密钥派生时迭代次数为100通常太小。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74501730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档