下午,
所以我对所有这些加密方法和用法都很陌生。我刚刚开始构建加密实现。现在我的加密和解密方法似乎工作正常。直到我读到我在 RijndaelManaged 类中使用硬编码 IV 时失败得很惨。
我到处都在读到,让每个加密文件的 IV 在“加密时间”唯一生成并保存在文件的开头/开头会更好(也更安全),因为其余的加密字节会在之后直接保存这。 (如果我理解正确的话)
我一直很难弄清楚我的问题,因为每次我加密文件时,我都会将 IV 写入前 16 个字节(正如类(class)、MSDN、Google 和该论坛上的一些人所建议的那样)文件的一部分,然后直接将其余的加密字节写入文件流。 (IV 以明文形式保存..或者未加密的字节 < 这也可以吗?)
我的问题是,当我尝试使用完全相同的 key 解密文件时失败了:在我开始读取文件 block 进行解密(缓冲)之前,我尝试读取文件的前 16 个字节以获得明文 IV 和在 RijndaelManaged 类实例中使用它。
这似乎失败了。我检查了一下,我想我可能在某个地方犯了一些小学生错误:因为一旦我想解密它,我似乎无法从加密文件中读取相同的 16 个字节。
这是我用来在加密之前进行文件处理的代码(不是加密本身)
using (RijndaelManaged RM = new RijndaelManaged())
using (FileStream StreamIN = new FileStream(FileIN, FileMode.Open, FileAccess.Read))
using (FileStream StreamOUT = new FileStream(FileOUT, FileMode.Append, FileAccess.Write))
{
//Setup Variable ChunkSize and The Total bytes Read into the streams
int ChunkSize = 1024 * 1024 * 32;
RM.GenerateIV();
foreach (var item in RM.IV)
{
Console.Write("[ " + item + "] ");
}
StreamOUT.Seek(0, SeekOrigin.Begin);
StreamOUT.Write(RM.IV, 0, RM.IV.Length);
StreamOUT.Seek(RM.IV.Length, SeekOrigin.Begin);
int TotalBytesRead = 0;
//File Buffer Implementation
for (long i = 0; i < StreamIN.Length; i += ChunkSize)
{
//ChunkData byte array determined by ChunkSize
byte[] ChunkData = new byte[ChunkSize];
//Current Bytes Read from the IN Stream
int BytesRead = 0;
while ((BytesRead = StreamIN.Read(ChunkData, 0, ChunkSize)) > 0)
{
//Call Encryption from local Class
Console.WriteLine("Bytes Read: {0}", TotalBytesRead += BytesRead);
ChunkData = Crypt.Encrypt(ChunkData, KeyBytes, RM.IV);
//Write byte array to File
StreamOUT.Write(ChunkData, 0, BytesRead);
}
}
}
这是我在解密之前处理文件的代码(不是解密本身)
using (RijndaelManaged RM = new RijndaelManaged())
using (FileStream StreamIN = new FileStream(FileIN, FileMode.Open, FileAccess.Read))
using (FileStream StreamOUT = new FileStream(FileOUT, FileMode.Append, FileAccess.Write))
{
//Setup Variable ChunkSize and The Total bytes Read into the streams
int ChunkSize = 1024 * 1024 * 32;
StreamIN.Seek(0, SeekOrigin.Begin);
int Read = StreamIN.Read(RM.IV, 0, 16);
StreamIN.Seek(RM.IV.Length, SeekOrigin.Begin);
int TotalBytesRead = 0;
foreach (var item in RM.IV)
{
Console.Write("[ " + item + "] ");
}
//File Buffer Implementation
for (long i = 0; i < StreamIN.Length; i += ChunkSize)
{
//ChunkData byte array determined by ChunkSize
byte[] ChunkData = new byte[ChunkSize];
//Current Bytes Read from the IN Stream
int BytesRead = 0;
while ((BytesRead = StreamIN.Read(ChunkData, 0, ChunkSize)) > 0)
{
Console.WriteLine("Bytes Read: {0}", TotalBytesRead += BytesRead);
//Call Decryption from local Class
ChunkData = Crypt.Decrypt(ChunkData, KeyBytes, RM.IV);
//Write byte Array to file
StreamOUT.Write(ChunkData, 0, BytesRead);
}
}
}
我想这就是全部?此外,到目前为止,“控制台”和其他无用的调用只是为了帮助我检查和找出问题。 我正在使用 Visual Studios 2010,并尝试实现 RijndaelManaged 类。
加密/解密方法通过我的 key 和 IV 传递给 FileChunks(字节数组),这些方法返回一个保存到流中的字节数组(加密)。
我希望我的问题很清楚?如果不是我会尝试更好地解释, 我到处阅读以寻求有关此特定问题的帮助,但此处发布的大多数其他问题都超出了我的范围。
我真的很感激任何帮助,我确定我在某个地方犯了 clown 错误..
谢谢!!
最佳答案
根据长期Framework guidelines ,看起来 SymmetricAlgorithm.IV
已被编写为不返回内部数组。这意味着它会返回给您一个副本,因此对其进行的后续更改不会反射(reflect)在 RijndaelManaged
实例中。
// Effectively reading the persisted value into a temporary array
// and throwing away the temporary.
int Read = StreamIN.Read(RM.IV, 0, 16);
为了使更改保持不变并将 IV 设置为持久值,您需要实际显式设置 IV
属性,而不是仅仅修改它之前返回的值。
byte[] persistedIv = new byte[16];
StreamIN.Read(persistedIv, 0, persistedIv.Length);
RM.IV = persistedIv;
关于c# - 正确的 C# Rijndael IV 用法/存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12998848/