c# 多层流中的加密 read/write
c# Encryption in a multi-layered Streams read/write
存在从多层数据创建的文件:
//input is not always the same, but the structure is, so for example there might be h4 and h5, but I will know that, so that is not the problem
private void generalizationofwrittendata(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt, byte[] somedata, int h1, int h2, int h3)
{
using (FileStream fs = new FileStream(outputfilename, FileMode.Create, FileAccess.Write))
{
using (BinaryWriter w = new BinaryWriter(fs, Encoding.ASCII))
{
//writing some data with binary writer
w.Write(h1);
w.Write(h2);
w.Write(h3);
using (FileStream fsIn = File.OpenRead(filename))
{
using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Write))
{
//writing the rest of data with crypto stream
cs.Write(somedata, 0, somedata.Length);
byte[] chunk = new byte[chunks];
int bytesRead = 0;
while ((bytesRead = fsIn.Read(chunk, 0, chunks)) > 0)
{
cs.Write(chunk, 0, bytesRead);
}
}
}
}
}
}
"generalizationofwrittendata" 以预期的方式完美运行。
现在的问题是将所有数据从文件中分离出来:
private void test(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt)
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, Encoding.ASCII))
{
//reading some not encrypted data
int h1 = br.ReadInt32();
int h2 = br.ReadInt32();
int h3 = br.ReadInt32();
using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Read))
{
using (BinaryReader br2 = new BinaryReader(cs, Encoding.ASCII))
{
//reading some encrypted data
byte[] somedata = br2.ReadBytes(someint);
//writing the rest of the data to file
using (FileStream fsOut = new FileStream(outputfilename, FileMode.Create))
{
byte[] chunk = new byte[chunks];
int bytesRead = 0;
while ((bytesRead = cs.Read(chunk, 0, chunks)) > 0)
{
fsOut.Write(chunk, 0, bytesRead);
}
}
}
}
}
}
}
这种方法根本行不通。只有 h1,h2,h3 可以通过这种方式被接收回来。一些数据会有所不同,写入的文件会比原始数据长,这让我认为问题出在 CryptoStream+BinaryReader 从文件开头读取。
可能你会建议我使用MemoryStream
,但这只对小文件有效,因此会导致内存超出范围异常。
我找到的唯一其他解决方案是 SubStream 实现,但不幸的是,当我在 "fs" 和 "cs" 之间使用它时,它导致了错误的 "somedata" 并且结果文件也有错误的数据.
也许有一种方法可以使用 Memory-Mapped Files 来做到这一点?但我不太确定我需要如何以这种方式处理它。
或者也许我遗漏了其他东西,因为使用 BinaryWriter 写入 "generalizationofwrittendata",然后使用 CryptoStream 似乎工作得很好。
更新#1:
因此,在收到回复后,我重新检查了所有代码,尤其是与 ICryptoTransform 相关的代码。 ICryptoTransform 绝对不是问题,这两种方法完全相同。
我注意到的另一件事是我无缘无故地使用了 "BinaryReader br2",所以我删除了它:
private void test(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt)
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, Encoding.ASCII))
{
//reading some not encrypted data
int h1 = br.ReadInt32();
int h2 = br.ReadInt32();
int h3 = br.ReadInt32();
using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Read))
{
//reading some encrypted data
byte[] somedata = new byte[someint];
cs.Read(somedata, 0, someint);
//writing the rest of the data to file
using (FileStream fsOut = new FileStream(outputfilename, FileMode.Create))
{
byte[] chunk = new byte[chunks];
int bytesRead = 0;
while ((bytesRead = cs.Read(chunk, 0, chunks)) > 0)
{
fsOut.Write(chunk, 0, bytesRead);
}
}
}
}
}
}
但不幸的是,这并没有解决问题,一些数据和写入文件的数据与原始数据不一样。
更新#2:
所以这是一个愚蠢的问题 - 我创建了 CreateEncryptor()
而不是 CreateDecryptor()
用于解密。
可能是我脸皮厚,你找fs合适的位置继续用同样的二进制文件不行吗reader?
我会试试这个,但设置加密密钥需要一些时间。
编辑:此外,您确定在解密时正确构建了 CryptoTransform 吗?
编辑:
当我使用以下代码时,您的代码按照您提供的方式工作:
byte[] testdata = new byte[] { 0x12, 0x34, 0x56 };
byte[] key;
byte[] iv;
String encryptedFile = "encrypted.bin";
private void buttonCrypt_Click(object sender, EventArgs e)
{
ICryptoTransform transform;
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
transform = rjndl.CreateEncryptor();
key = (byte[])rjndl.Key.Clone();
iv = (byte[])rjndl.IV.Clone();
generalizationofwrittendata("plain.bin",testdata.Length,1,encryptedFile,transform,testdata,0x0abbccdd,0x01223344,0x09887766);
}
private void buttonDecrypt_Click(object sender, EventArgs e)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
var transform = rjndl.CreateDecryptor(key, iv);
test(encryptedFile, testdata.Length, 1, "decrypted.bin", transform);
}
其他数据读取为{0x12,0x34,0x56},h1到h3是我提供的值,decrypted.bin与plain.bin相同。
这表明您提供给解密器的密钥存在问题。
更新 1:
我修改了我的测试工具以使用 Aes:
private void buttonCrypt_Click(object sender, EventArgs e)
{
ICryptoTransform transform;
AesManaged Aes = new AesManaged();
Aes.KeySize = 256;
Aes.BlockSize = 128;
Aes.Mode = CipherMode.CBC;
Aes.Padding = PaddingMode.PKCS7;
transform = Aes.CreateEncryptor();
key = (byte[])Aes.Key.Clone();
iv = (byte[])Aes.IV.Clone();
generalizationofwrittendata("plain.bin",testdata.Length,1,encryptedFile,transform,testdata,0x0abbccdd,0x01223344,0x09887766);
}
private void buttonDecrypt_Click(object sender, EventArgs e)
{
AesManaged Aes = new AesManaged();
Aes.KeySize = 256;
Aes.BlockSize = 128;
Aes.Mode = CipherMode.CBC;
Aes.Padding = PaddingMode.PKCS7;
var transform = Aes.CreateDecryptor(key, iv);
test(encryptedFile, testdata.Length, 1, "decrypted.bin", transform);
}
结果是一样的,它仍然像你最初发布的那样有效。
我正在让 Aes 创建一个密钥和我保存的初始化向量,您需要检查加密和解密都使用 完全 相同的值调用您的 Aes 生成器。另外,请确保您使用 Aes.CreateEncyptor() 进行加密并使用 Aes.CreateDecryptor() 进行解密。
问题确实出在密钥上,所以我的建议是在创建加密器并转储 key/iv 后中断,然后在创建解密器并检查它们是否为字节后执行相同操作字节相同。
存在从多层数据创建的文件:
//input is not always the same, but the structure is, so for example there might be h4 and h5, but I will know that, so that is not the problem
private void generalizationofwrittendata(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt, byte[] somedata, int h1, int h2, int h3)
{
using (FileStream fs = new FileStream(outputfilename, FileMode.Create, FileAccess.Write))
{
using (BinaryWriter w = new BinaryWriter(fs, Encoding.ASCII))
{
//writing some data with binary writer
w.Write(h1);
w.Write(h2);
w.Write(h3);
using (FileStream fsIn = File.OpenRead(filename))
{
using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Write))
{
//writing the rest of data with crypto stream
cs.Write(somedata, 0, somedata.Length);
byte[] chunk = new byte[chunks];
int bytesRead = 0;
while ((bytesRead = fsIn.Read(chunk, 0, chunks)) > 0)
{
cs.Write(chunk, 0, bytesRead);
}
}
}
}
}
}
"generalizationofwrittendata" 以预期的方式完美运行。
现在的问题是将所有数据从文件中分离出来:
private void test(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt)
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, Encoding.ASCII))
{
//reading some not encrypted data
int h1 = br.ReadInt32();
int h2 = br.ReadInt32();
int h3 = br.ReadInt32();
using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Read))
{
using (BinaryReader br2 = new BinaryReader(cs, Encoding.ASCII))
{
//reading some encrypted data
byte[] somedata = br2.ReadBytes(someint);
//writing the rest of the data to file
using (FileStream fsOut = new FileStream(outputfilename, FileMode.Create))
{
byte[] chunk = new byte[chunks];
int bytesRead = 0;
while ((bytesRead = cs.Read(chunk, 0, chunks)) > 0)
{
fsOut.Write(chunk, 0, bytesRead);
}
}
}
}
}
}
}
这种方法根本行不通。只有 h1,h2,h3 可以通过这种方式被接收回来。一些数据会有所不同,写入的文件会比原始数据长,这让我认为问题出在 CryptoStream+BinaryReader 从文件开头读取。
可能你会建议我使用MemoryStream
,但这只对小文件有效,因此会导致内存超出范围异常。
我找到的唯一其他解决方案是 SubStream 实现,但不幸的是,当我在 "fs" 和 "cs" 之间使用它时,它导致了错误的 "somedata" 并且结果文件也有错误的数据.
也许有一种方法可以使用 Memory-Mapped Files 来做到这一点?但我不太确定我需要如何以这种方式处理它。 或者也许我遗漏了其他东西,因为使用 BinaryWriter 写入 "generalizationofwrittendata",然后使用 CryptoStream 似乎工作得很好。
更新#1:
因此,在收到回复后,我重新检查了所有代码,尤其是与 ICryptoTransform 相关的代码。 ICryptoTransform 绝对不是问题,这两种方法完全相同。
我注意到的另一件事是我无缘无故地使用了 "BinaryReader br2",所以我删除了它:
private void test(string filename, int someint, int chunks, string outputfilename, ICryptoTransform crypt)
{
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (BinaryReader br = new BinaryReader(fs, Encoding.ASCII))
{
//reading some not encrypted data
int h1 = br.ReadInt32();
int h2 = br.ReadInt32();
int h3 = br.ReadInt32();
using (CryptoStream cs = new CryptoStream(fs, crypt, CryptoStreamMode.Read))
{
//reading some encrypted data
byte[] somedata = new byte[someint];
cs.Read(somedata, 0, someint);
//writing the rest of the data to file
using (FileStream fsOut = new FileStream(outputfilename, FileMode.Create))
{
byte[] chunk = new byte[chunks];
int bytesRead = 0;
while ((bytesRead = cs.Read(chunk, 0, chunks)) > 0)
{
fsOut.Write(chunk, 0, bytesRead);
}
}
}
}
}
}
但不幸的是,这并没有解决问题,一些数据和写入文件的数据与原始数据不一样。
更新#2:
所以这是一个愚蠢的问题 - 我创建了 CreateEncryptor()
而不是 CreateDecryptor()
用于解密。
可能是我脸皮厚,你找fs合适的位置继续用同样的二进制文件不行吗reader?
我会试试这个,但设置加密密钥需要一些时间。
编辑:此外,您确定在解密时正确构建了 CryptoTransform 吗?
编辑: 当我使用以下代码时,您的代码按照您提供的方式工作:
byte[] testdata = new byte[] { 0x12, 0x34, 0x56 };
byte[] key;
byte[] iv;
String encryptedFile = "encrypted.bin";
private void buttonCrypt_Click(object sender, EventArgs e)
{
ICryptoTransform transform;
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
transform = rjndl.CreateEncryptor();
key = (byte[])rjndl.Key.Clone();
iv = (byte[])rjndl.IV.Clone();
generalizationofwrittendata("plain.bin",testdata.Length,1,encryptedFile,transform,testdata,0x0abbccdd,0x01223344,0x09887766);
}
private void buttonDecrypt_Click(object sender, EventArgs e)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
var transform = rjndl.CreateDecryptor(key, iv);
test(encryptedFile, testdata.Length, 1, "decrypted.bin", transform);
}
其他数据读取为{0x12,0x34,0x56},h1到h3是我提供的值,decrypted.bin与plain.bin相同。
这表明您提供给解密器的密钥存在问题。
更新 1:
我修改了我的测试工具以使用 Aes:
private void buttonCrypt_Click(object sender, EventArgs e)
{
ICryptoTransform transform;
AesManaged Aes = new AesManaged();
Aes.KeySize = 256;
Aes.BlockSize = 128;
Aes.Mode = CipherMode.CBC;
Aes.Padding = PaddingMode.PKCS7;
transform = Aes.CreateEncryptor();
key = (byte[])Aes.Key.Clone();
iv = (byte[])Aes.IV.Clone();
generalizationofwrittendata("plain.bin",testdata.Length,1,encryptedFile,transform,testdata,0x0abbccdd,0x01223344,0x09887766);
}
private void buttonDecrypt_Click(object sender, EventArgs e)
{
AesManaged Aes = new AesManaged();
Aes.KeySize = 256;
Aes.BlockSize = 128;
Aes.Mode = CipherMode.CBC;
Aes.Padding = PaddingMode.PKCS7;
var transform = Aes.CreateDecryptor(key, iv);
test(encryptedFile, testdata.Length, 1, "decrypted.bin", transform);
}
结果是一样的,它仍然像你最初发布的那样有效。
我正在让 Aes 创建一个密钥和我保存的初始化向量,您需要检查加密和解密都使用 完全 相同的值调用您的 Aes 生成器。另外,请确保您使用 Aes.CreateEncyptor() 进行加密并使用 Aes.CreateDecryptor() 进行解密。
问题确实出在密钥上,所以我的建议是在创建加密器并转储 key/iv 后中断,然后在创建解密器并检查它们是否为字节后执行相同操作字节相同。