我正在尝试使用AES256算法进行加密和解密,我有以下代码。
public string Encrypt(string dataToEncrypt, string key)
{
if (dataToEncrypt == null || dataToEncrypt.Length <= 0)
throw new ArgumentNullException("plainText");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("Key");
var iv = GenerateRandomNumber(16);
using (var aes = new AesCryptoServiceProvider())
{
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Convert.FromBase64String(key);
aes.IV = iv;
byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
using (var memoryStream = new MemoryStream())
{
var cryptoStream = new CryptoStream(memoryStream,
aes.CreateEncryptor(),
CryptoStreamMode.Write);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
return Convert.ToBase64String(memoryStream.ToArray());
}
}
}
public string DecryptReturnsString(string dataToDecrypt, string key)
{
if (dataToDecrypt == null || dataToDecrypt.Length <= 0)
throw new ArgumentNullException("dataToDecrypt");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("Key");
using (var aes = new AesCryptoServiceProvider())
{
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Convert.FromBase64String(key);
byte[] data= Convert.FromBase64String(dataToDecrypt);
aes.IV = getIV(data);
using (var memoryStream = new MemoryStream())
{
var cryptoStream = new CryptoStream(memoryStream, aes.CreateDecryptor(),
CryptoStreamMode.Write);
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
var decryptBytes = Encoding.UTF8.GetString(memoryStream.ToArray());
return decryptBytes;
}
}
}
public byte[] GenerateRandomNumber(int length)
{
using (var randomNumberGenerator = new RNGCryptoServiceProvider())
{
var randomNumber = new byte[length];
randomNumberGenerator.GetBytes(randomNumber);
return randomNumber;
}
}
private static byte[] getIV(byte[] arr)
{
byte[] IV = new byte[16];
Array.Copy(arr, 0, IV, 0, 16);
return IV;
}
在这里,我尝试从加密的字符串中获取IV,但是在调试时,最初生成的IV和提取的IV是不同的,因此它给了我一个例外,即“填充无效且无法删除。” / p>
任何人都可以看看我的GetIV()方法,让我知道我在哪里做错了。
答案 0 :(得分:0)
在CBC操作模式下的IV必须以纯文本形式发送,否则无法解密。这没有安全问题。
如罗伯特所说,将其放在流的开头。
var mergedStream = new MergedStream(new Stream
{
new MemoryStream(iv),
cryptoStream,
}
答案 1 :(得分:0)
有两个问题。
似乎您不是沿着密文发送IV(本身并没有完成)。惯常做法是将IV放在密文之前。因此,正如罗伯特(Robert)所说,您可以在加密之前直接将IV写入内存流
解密时,您可以读取IV(数据的第一个字节,但仅解密其余部分(子数组16 .. length)