c# - 在不同的运行期间解密加密的字符串
问题描述
下面的代码工作正常并加密:
hello world
至:
BgGUY2eR7GfumjbQr58tBQ==
跑步。下次这可能会有所不同,例如:
CYIM7V/h3iXu5PYzwmQ33g==
我认为这是这个算法的重点。如何解密不久前加密的字符串?
如果我做:
static void Main(string[] args)
{
var key = @"abcdefghijklmnopqrstuvw==";
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Key = Convert.FromBase64String(key);
aesAlg.GenerateIV();
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
var helloWorld = DecryptProperty(decryptor, "CYIM7V/h3iXu5PYzwmQ33g==");
}
}
我得到:
System.Security.Cryptography.CryptographicException
HResult=0x80131430
Message=Padding is invalid and cannot be removed.
Source=System.Core
StackTrace:
at System.Security.Cryptography.CapiSymmetricAlgorithm.DepadBlock(Byte[] block, Int32 offset, Int32 count)
at System.Security.Cryptography.CapiSymmetricAlgorithm.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.Read(Byte[] buffer, Int32 offset, Int32 count)
at System.IO.StreamReader.ReadBuffer()
at System.IO.StreamReader.ReadToEnd()
at crypt.Program.DecryptProperty(ICryptoTransform decryptor, String valueToDecrypt)
有任何想法吗?如何解密过去使用密钥加密的字符串?谢谢!
工作代码:
using System;
using System.IO;
using System.Security.Cryptography;
namespace crypt
{
class Program
{
static void Main(string[] args)
{
var key = @"abcdefghijklmnopqrstuvw==";
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Key = Convert.FromBase64String(key);
aesAlg.GenerateIV();
var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
var encHelloWorld = EncryptProperty(encryptor, "hello world");
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
var helloWorld = DecryptProperty(decryptor, encHelloWorld);
}
}
private static string EncryptProperty(ICryptoTransform encryptor, string valueToEncrypt)
{
byte[] encrypted;
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (var swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(valueToEncrypt);
}
encrypted = msEncrypt.ToArray();
}
}
return Convert.ToBase64String(encrypted);
}
private static string DecryptProperty(ICryptoTransform decryptor, string valueToDecrypt)
{
string decrypted;
using (var msDecrypt = new MemoryStream(Convert.FromBase64String(valueToDecrypt)))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
decrypted = srDecrypt.ReadToEnd();
}
}
}
return decrypted;
}
}
}
解决方案
您在每次解密时都会生成一个新的(随机)初始化向量。解密时需要使用与加密时相同的 IV。
您的示例代码有效,因为它使用相同的算法状态(包括 IV)在同一次运行中进行加密和解密,但不会跨运行工作,因为GenerateIV
每次都会创建一个新的随机缓冲区。
通常,人们会在加密值之前写入 IV,然后将它们存储在一起。
推荐阅读
- python - 将数据从 MSSQL 数据库导入二维数组
- java - Vaadin 14 组件未显示/不可见
- php - 从字符串中获取邮政编码
- php - 按关系距离排列的地理空间顺序
- bcrypt - Bcrypt docker passwd 使用 --admin-passwd
- c# - Masstransit 如何进行高级请求/回复模式
- python - 如何更改xml中节点属性的顺序?
- javascript - 检查日期是否大于其他日期(dd/mm/yyyy)
- node.js - 我在 AWS Lambda NodeJS 上运行 bcrypt 时遇到问题,有人可以帮我吗?
- c# - .NET Core Web API 在哪里实现业务逻辑?