难以理解 RijndaelManaged 加密的结果

Difficulty understanding result of RijndaelManaged encryption

在阅读了很多关于 SO 的问题和答案之后,我还没有弄清楚为什么我在下面编写的代码会产生意想不到的结果。我使用 Rfc2898DeriveBytes class 生成一个 128 位密钥以供 RijndaelManaged class 使用。我使用 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 属性 所以我无法检查是否有任何内容写入它。我也知道我没有在结果中预先添加盐或 IV,我还没有这样做。

仅解决您的零长度 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()

即使假设代码在上述更改后按预期工作,代码中还有各种其他安全问题超出了此答案的范围。