c# - 关闭解密时 CryptoStream 引发错误
问题描述
我正在尝试使用 RijndaelManaged 类加密纯文本,然后解密加密的字符串以最终具有相同的纯文本。
加密纯文本时一切正常,如下所示,
protected static string AESEncrypt(string plainText, string key)
{
byte[] encryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var keyHold = new Rfc2898DeriveBytes(key, saltBytes, 1000);
aes.Key = keyHold.GetBytes(aes.KeySize / 8);
aes.IV = keyHold.GetBytes(aes.BlockSize / 8);
aes.Mode = CipherMode.CBC;
var bytesToBeEncrypted = Encoding.UTF8.GetBytes(plainText);
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return Convert.ToBase64String(encryptedBytes);
}
例如,我"encryptMe"
通过调用上述函数来加密这个纯文本var encryptedString = AESEncrypt(plainText, "lockMe");
。结果是nKytZ86r0DDKSzD3ph+ntg==
。
然后我将该加密字符串发送到下面提到的函数,
protected static string AESDecrypt(string cryptedText, string key)
{
byte[] decryptedBytes = null;
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var keyHold = new Rfc2898DeriveBytes(key, saltBytes, 1000);
aes.Key = keyHold.GetBytes(aes.KeySize / 8);
aes.IV = keyHold.GetBytes(aes.BlockSize / 8);
aes.Mode = CipherMode.CBC;
var bytesToBeDDecrypted = Encoding.UTF8.GetBytes(cryptedText);
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDDecrypted, 0, bytesToBeDDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return Encoding.UTF8.GetString(decryptedBytes);
}
The input data is not a complete block
在此方法中,代码在离开时会引发错误CryptoStream
。
我的KeySize
和BlockSize
都可以被 8 整除,我看不到我忽略了什么。
解决方案
在AESDecrypt
你有:
var bytesToBeDDecrypted = Encoding.UTF8.GetBytes(cryptedText);
由于您正在传递 base-64 编码密码,因此应该改为
var bytesToBeDDecrypted = Convert.FromBase64String(cryptedText);
您还应该进行一些安全改进。您应该将迭代次数从 1000 增加到更大的值,至少 65K。salt 应至少为 12 个字节,并且应为每次加密随机生成。它不需要保密,通常很方便将其添加到密码中。然后解密器从传入的密文中提取盐。您还应该使用消息验证码 (MAC) 来防止篡改。请注意,AES-GCM 模式以及其他一些模式包括此 MAC 作为其操作的组成部分。但是,如果 AES-GCM 不可用,那么 HMAC-SHA256 可能会并且是可以接受的。
推荐阅读
- python - 基于当前行和上一行的用户定义函数
- google-cloud-firestore - Firestore 安全规则授予用户对文档及其子集合的读/写权限不起作用
- python - 有时在 Firefox 中找不到定位器
- php - 安装包 spatie 权限后未定义类型 Intervention\Image\Facades\Image
- python-3.x - 在 pandas 中根据月份对数据进行分组,然后删除除最新的一个 Python 之外的所有条目
- javascript - 除非单击特殊链接,否则离开页面之前的Javascript事件?
- c# - 具有重复孔名的 NLog 结构化日志记录
- powershell - WPF - 单击 ListView 中的项目
- javascript - Discord.js 如何在嵌入中添加customemoji?
- c++ - 在 VS19 中调试 C++ 时出现错误代码 0x80070002