【发布时间】:2020-01-21 17:03:48
【问题描述】:
下面的代码可以正常工作并加密:
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 可以附加或附加到数据中。如果目标不是某种数据存储,则找个地方存储它
-
谢谢,那么我可以获取它们并以某种方式对其进行硬编码吗?存储不是问题(将进入 App.config 开始)。谢谢。
-
永远不要对 IV 进行硬编码或重用它们。始终创建一个不同的并将其与加密块一起存储。
-
@BorisB。感谢在我们的案例中,我们将加密的数据发送给第 3 方,当我们取回它时,我们会对其进行解密。您是否建议发送带有加密数据的 IV?我可以不简单地将 IV 存储为我的应用程序/数据库中的字符串 (?) 吗?谢谢。抱歉,这对我来说是全新的。
标签: c# encryption