在阅读了很多关于SO的问题和答案之后,我还没弄清楚为什么我在下面编写的代码会产生意想不到的结果。我使用Rfc2898DeriveBytes
类生成一个128位密钥,用于RijndaelManaged
类。我使用GenerateIV()
生成IV。我在这里做错了吗?我所看到的许多代码示例都非常恰到好处。
string text = "TEXT TO ENCRYPT";
string key = "MY_KEY";
byte[] saltRaw = BitConverter.GetBytes((long)text.Length);
Rfc2898DeriveBytes deriver = new Rfc2898DeriveBytes(key, saltRaw);
byte[] keyRaw = deriver.GetBytes(32);
RijndaelManaged rij = new RijndaelManaged();
rij.Key = keyRaw;
rij.GenerateIV();
ICryptoTransform encryptor = rij.CreateEncryptor(rij.Key, rij.IV);
MemoryStream sMemory = new MemoryStream();
CryptoStream sCrypt = new CryptoStream(sMemory, encryptor, CryptoStreamMode.Write);
StreamWriter sWriter = new StreamWriter(sCrypt);
sWriter.Write(text);
byte[] r = sMemory.ToArray();
sWriter.Dispose();
sCrypt.Dispose();
sMemory.Dispose();
encryptor.Dispose();
return r; // length of r is 0.
这里的问题是byte[] r
的长度为0,因此没有任何内容写入内存流。 CryptoStream没有实现length
属性,所以我无法检查是否有任何内容被写入。我也知道我没有预先准备Salt或IV预测结果,我还没有这样做。
答案 0 :(得分:1)
仅解决您的零长r
问题,这是由于StreamWriter
内的缓冲,所以当您尝试获取MemoryStream
的内容时,实际上什么都没有已被写入。
byte[] r;
using (var sMemory = new MemoryStream())
{
using (var sCrypt = new CryptoStream(sMemory, encryptor, CryptoStreamMode.Write))
{
using (var sWriter = new StreamWriter(sCrypt))
{
sWriter.Write(text);
}
}
r = sMemory.ToArray();
}
我强烈建议您使用上面的using()
块,而不是显式调用Dispose()
,因为这样可以确保即使在异常的情况下也能正确处理,并且还有助于避免在处置后使用对象,或者根本没有打电话给Dispose()
。
即使假设代码在上述更改后按预期工作,代码中还存在各种其他安全问题,超出了本答案的范围。