c# - 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();
它正在解密为垃圾数据的行。
这会是什么原因?我错过了什么吗?你能帮我解决这个问题吗
解决方案
由于您没有回答@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;
}
}
推荐阅读
- javascript - 如何让 DOM 元素的更新更高效?
- azure - Azure 函数将文件上传到 Azure Blob
- python-3.x - 在 groupby 聚合函数中传递参数
- google-app-maker - 我们如何发布具有自定义域的 Web 应用程序?
- ios - 如何在 swift 4 上从 didFinishLaunchingWithOptions 获取通知中心数据
- javascript - 在Javascript中向数组添加元素
- docker - nginx ssl docker没有这样的文件或目录
- pipeline - 在数据工厂管道目标中添加文件名作为列
- javascript - 如何创建一个 html 工具提示
- javascript - Gulp-Change 给 TypeError | 反应应用