我已经解决了这个问题几个小时了,我仍然无法找到它发生的原因。
我有一个用AES加密的字符串,然后解密回原来的状态。但是,解密似乎修改了原始字符串,破坏了第一个字节。
而不是返回bc85f420763f79e6
9becb ...
,而是返回?OqG?b3Mf~ J???j
9becb ...
,然后继续返回其余的明文正确。
以下是我用来加密和解密的方法:
private byte[] EncryptAES256(string text, byte[] key)
{
if (string.IsNullOrWhiteSpace(text)) throw new ArgumentNullException("text");
if (key == null || key.Length <= 0) throw new ArgumentNullException("key");
byte[] encryptedText;
try
{
AesManaged aes = new AesManaged();
aes.Padding = PaddingMode.PKCS7;
aes.GenerateIV();
aes.Key = key;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(text);
}
encryptedText = msEncrypt.ToArray();
}
}
}
catch (Exception ex)
{
Exception exceptionToBeThrown = new Exception(ex.Message, ex.InnerException);
throw exceptionToBeThrown;
}
return encryptedText;
}
private string DecryptAES256(byte[] text, byte[] key)
{
if (text == null || text.Length <= 0) throw new ArgumentNullException("text");
if (key == null || key.Length <= 0) throw new ArgumentNullException("key");
string decryptedText;
try
{
AesManaged aes = new AesManaged();
aes.Padding = PaddingMode.PKCS7;
aes.GenerateIV();
aes.Key = key;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream msDecrypt = new MemoryStream(text))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
decryptedText = srDecrypt.ReadToEnd();
}
}
}
}
catch (Exception ex)
{
Exception exceptionToBeThrown = new Exception(ex.Message, ex.InnerException);
throw exceptionToBeThrown;
}
return decryptedText;
}
我弄乱了什么吗?
答案 0 :(得分:3)
加密和解密时使用的是不同的IV。 解密时,必须指定与加密数据时使用的IV相同的IV。
来自GenerateIV的文件(强调我的):
生成随机初始化向量(IV)以用于算法。
您可以使用在代码中定义的常量IV并传递给AesManaged实例,也可以存储用于加密数据的IV以及数据,然后在解密其余部分之前读取它。 / p>
答案 1 :(得分:3)
这是失败的原因是因为您没有设置IV键。相反,您为加密和解密方法生成两个不同的IV。
aes.GenerateIV();
每当您想要加密和解密数据时,您必须确保Salt en IV是相同的。您要做的是将加密方法中的IV添加到加密字节数组的开头。类似的东西:
byte[] IV = aesAlg.IV;
byte[] combinedIvCt = new byte[IV.Length + encrypted.Length];
Array.Copy(IV, 0, combinedIvCt, 0, IV.Length);
Array.Copy(encrypted, 0, combinedIvCt, IV.Length, encrypted.Length);
return Convert.ToBase64String(combinedIvCt.ToArray());
一旦解密,就会尝试解密加密结果的前16个字节。这将是你的IV键:
byte[] IV = new byte[16];
byte[] Encoded = new byte[inputAsByteArray.Length - IV.Length];
Array.Copy(inputAsByteArray, 0, IV, 0, IV.Length);
Array.Copy(inputAsByteArray, IV.Length, Encoded, 0, Encoded.Length);
//later in your code....
//Encoding = the data you are going to decrypt.
aesAlg.IV = IV;
如果您想添加盐,也可以这样做。无论你做什么,但从不硬编码你的盐或IV。这是一本有趣的读物:https://security.stackexchange.com/questions/49031/is-it-safe-to-write-the-salt-and-or-the-iv-at-the-beggining-of-an-encrypted-file