首页 > 解决方案 > C# AES 解密返回垃圾数据

问题描述

我正在使用 aes.js 加密纯文本并在 c# 中解密

JS中的加密代码

var aesKey = "87E67EF6-ECFB-4295-ACA3-B3F06BE489B1-87E67EF6-ECFB-4295-ACA3-B3F06BE489B1";
var encrypted = CryptoJS.AES.encrypt(JSON.stringify(emailParams), aesKey, {
                keySize: 256,
                padding: CryptoJS.pad.Pkcs7
});
var encAesKey = aesKey;
var encData = new Object();
encData.pId = 1234;
encData.encAesKey = encAesKey;
encData.encAesData = encrypted.toString();

我正在尝试解密 C# 中的加密字符串

byte[] data = Convert.FromBase64String(cipherText);
MemoryStream ms = new MemoryStream();
Rijndael alg = Rijndael.Create();
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { 0x43, 0x72, 0x6e, 0x6d, 0x54, 0x4d, 0x65, 0x94, 0x16, 0x32, 0x44, 0x84, 0x7e, 0x18, 0x64, 0x76, 0x6e, 0x63, 0x64, 0x7a, 0x5f, 0x84, 0x7f, 0x9a });
alg.KeySize = 256;
alg.Key = pdb.GetBytes(32);
alg.IV = pdb.GetBytes(16);
alg.Padding = PaddingMode.PKCS7;
CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(data, 0, data.Length);
//cs.Close();
string st = System.Text.Encoding.ASCII.GetString(ms.ToArray());
return st;

如果我取消注释该行cs.Close();,它将在该行抛出“填充无效且无法删除”。如果我评论cs.Close();它正在解密为垃圾数据的行。 在此处输入图像描述

这会是什么原因?我错过了什么吗?你能帮我解决这个问题吗

标签: c#aes

解决方案


由于您没有回答@Topaco 关于您的要求的问题,我更改了我的示例代码以显示使用 AES CBC 256 和 PBKDF2 密钥派生的跨平台加密。

请注意,我懒得将我的代码用于您的特定数据,所以我让您自己来获取您喜欢的输入数据。

安全警告:由于在浏览器中运行 Javascript,这两个代码都没有任何异常处理,并且 PBKDF2 迭代次数 (1000) 很低。数据的盐和iv处理和拆分也需要一些改进。

Javascript 代码(用于加密)提供(连接的)盐、iv 和加密数据的输出,这些数据在 C# 端(用于解密)被拆分以提供 PBKDF2 和 AES 解密函数。

这是两个程序的输出 - 您可以在此处运行两个程序的实时示例(JS:https ://repl.it/@javacrypto/SoJsAesCbcPbkdf2EncryptOnly#index.js,C#: https : //repl.it/@javacrypto /SoCAesCbcPbkdf2DecryptOnly)。

Javascript:

SO AES CBC 256 PBKDF2 encryption only (JS)
transitmessage: 8c22a29d14f5e1e1582a795bfec8e4f8b91af5e6390c1b0b598b7d0d63cd2e6f1LSz9IT93Fe6OwWYZ7Dpj1LrSIwsV46ccs3oV3A2FoBCH6+8Jp+fSLprYqh1adIJ

C#:

SO AES CBC 256 PBKDF2 decryption only (C#)
plaintext: The quick brown fox jumps over the lazy dog

Javascript代码:

var CryptoJS = require("crypto-js");

console.log('SO AES CBC 256 PBKDF2 encryption only (JS)');

var keySize = 256;
var saltSize = 128;
var ivSize = 128;
var iterations = 1000;

var message = "The quick brown fox jumps over the lazy dog";

var aesKey = "87E67EF6-ECFB-4295-ACA3-B3F06BE489B1-87E67EF6-ECFB-4295-ACA3-B3F06BE489B1";

// pbkdf2
var salt = CryptoJS.lib.WordArray.random(saltSize/8);
var key = CryptoJS.PBKDF2(aesKey, salt, {
    keySize: keySize/32,
    iterations: iterations
  });

// encrypt
var iv = CryptoJS.lib.WordArray.random(ivSize/8);
var encrypted = CryptoJS.AES.encrypt(message, key, { 
    iv: iv, 
    padding: CryptoJS.pad.Pkcs7,
    mode: CryptoJS.mode.CBC
  });
var transitmessage = salt.toString()+ iv.toString() + encrypted.toString();
console.log('transitmessage:', transitmessage);

C#代码:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Program {

    public static void Main() {
        Console.WriteLine("SO AES CBC 256 PBKDF2 decryption only (C#)");

    const int ITERATIONS = 1000; // number of pbkdf2 iterations
    String aesData = "87E67EF6-ECFB-4295-ACA3-B3F06BE489B1-87E67EF6-ECFB-4295-ACA3-B3F06BE489B1";
    // data coming from javascript CryptoJS encryption
    string data = "8c22a29d14f5e1e1582a795bfec8e4f8b91af5e6390c1b0b598b7d0d63cd2e6f1LSz9IT93Fe6OwWYZ7Dpj1LrSIwsV46ccs3oV3A2FoBCH6+8Jp+fSLprYqh1adIJ";

    // splitting the datastring
    string saltHex = data.Substring(0, 32);
    string ivHex = data.Substring(32, 32);
    string cipherBase64 = data.Substring(64, (data.Length - 64));
    //Console.WriteLine("saltHex: " + saltHex);
    //Console.WriteLine("ivHex: " + ivHex);
    //Console.WriteLine("cipherBase64: " + cipherBase64);

    // pbkdf2
    Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(aesData, 
    StringToByteArray(saltHex), ITERATIONS);
    byte[] key = pbkdf2.GetBytes(32);

    // decryption
    string decryptedtext;
    using(Aes aesAlg = Aes.Create()) {
            aesAlg.Key = key;
            byte[] IV = StringToByteArray(ivHex);
            byte[] cipherText = Convert.FromBase64String(cipherBase64);
            aesAlg.IV = IV;
            aesAlg.Mode = CipherMode.CBC;
            ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            using(var msDecrypt = new MemoryStream(cipherText)) {
                using(var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
                    using(var srDecrypt = new StreamReader(csDecrypt)) {
                        decryptedtext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }
    Console.WriteLine("plaintext: " + decryptedtext);
    }

  static byte[] StringToByteArray(String hex) {
    int NumberChars = hex.Length;
    byte[] bytes = new byte[NumberChars / 2];
    for (int i = 0; i < NumberChars; i += 2)
    bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
    return bytes;
  }
}

推荐阅读