C# 加密大文件并添加到ZIP
我的目标是加密大型(cca 10 GB)输入文件,并将其附加到现有的System.IO.Packaging包中。我只能使用.NETFramework 3.5,不能使用第三方库 我尝试了十种方法,但没有成功。我尝试将输入读取到流,对其进行加密并保存到PackagePart。我尝试一个字节接一个字节地读取输入文件,然后对读取的字节进行加密,并将其从PackagePart附加到流中。每次我发现一个新问题(例如CryptoStream不支持查找等) 请告诉我正确的路好吗C# 加密大文件并添加到ZIP,c#,file,encryption,zip,C#,File,Encryption,Zip,我的目标是加密大型(cca 10 GB)输入文件,并将其附加到现有的System.IO.Packaging包中。我只能使用.NETFramework 3.5,不能使用第三方库 我尝试了十种方法,但没有成功。我尝试将输入读取到流,对其进行加密并保存到PackagePart。我尝试一个字节接一个字节地读取输入文件,然后对读取的字节进行加密,并将其从PackagePart附加到流中。每次我发现一个新问题(例如CryptoStream不支持查找等) 请告诉我正确的路好吗 //创建zip文件的方法(仅示例
//创建zip文件的方法(仅示例)
公共静态无效AppendToZip(SomeType encryptedData)
{
使用(Package zip=Package.Open(@“C:\myarchive.zip”,FileMode.OpenOrCreate))
{
uriuri=PackUriHelper.CreatePartUri(新Uri(“/files/test.enc”,UriKind.Relative));
尝试
{
part=zip.GetPart(uri);
}
接住
{
}
if(part==null)
{
part=zip.CreatePart(uri,“,CompressionOption.max);
}
使用(Stream dest=part.GetStream())
{
//如何将加密数据写入目标流?
}
}
}
//加密文件的示例方法
私有静态无效加密(字符串输入文件、字符串加密文件、字节[]密码字节、字节[]盐字节)
{
FileStream fsCrypt=newfilestream(cryptFile,FileMode.Create);
RijndaelManaged AES=新的RijndaelManaged();
AES.KeySize=256;
AES.BlockSize=128;
var key=新的Rfc2898DeriveBytes(passwordBytes,saltBytes,1000);
AES.Key=Key.GetBytes(AES.KeySize/8);
AES.IV=key.GetBytes(AES.BlockSize/8);
AES.Padding=PaddingMode.zero;
AES.Mode=CipherMode.CBC;
CryptoStream cs=新加密流(fsCrypt,AES.CreateEncryptor(),CryptoStreamMode.Write);
FileStream fsIn=newfilestream(inputFile,FileMode.Open);
int数据;
而((data=fsIn.ReadByte())!=-1)
{
cs.WriteByte((字节)数据);
}
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
试试这个-利用块大小来提高性能。我用3.5 GB的ISO成功地做到了这一点。但是压缩加密内容的zip文件要大得多,所以正如另一个人所说,最好先压缩文件,然后再加密。但我不知道你的要求,所以这里是这个
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Packaging;
namespace ZipTest
{
class Program
{
static void Main(string[] args)
{
// Block size we apply to all reads / writes
const int BLOCK_SIZE = 65536;
// The zip file we're using
var zipFileName = @"C:\temp\ZipSO\MyZip.zip";
// Password for encryption
var password = "ThisIsMyPassword";
// Name of temp file where we'll encrypt the file first
var intermediateFile = @"C:\temp\ZipSO\Intermediate_" + Guid.NewGuid().ToString();
// File we're encrypting / adding to archive
var inputFile = @"C:\temp\ZipSO\InputFile.txt";
// Salt for encryption
var salt = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
// For the new / existing package part
PackagePart part = null;
// Open the archive
using (var zip = Package.Open(zipFileName, System.IO.FileMode.OpenOrCreate))
{
// Uri for the part
var uri = PackUriHelper.CreatePartUri(new Uri("/files/test.enc", UriKind.Relative));
// Get existing part if found, or create new
if (zip.PartExists(uri))
part = zip.GetPart(uri);
else
part = zip.CreatePart(uri, "", CompressionOption.Maximum);
// Encrypt the file first
var passBytes = System.Text.Encoding.ASCII.GetBytes(password);
using (var fs = new System.IO.FileStream(intermediateFile, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write))
{
var key = new System.Security.Cryptography.Rfc2898DeriveBytes(passBytes, salt, 1000);
var keySize = 256;
var blockSize = 128;
var aes = new System.Security.Cryptography.RijndaelManaged()
{
KeySize = keySize,
BlockSize = blockSize,
Key = key.GetBytes(keySize / 8),
IV = key.GetBytes(blockSize / 8),
Padding = System.Security.Cryptography.PaddingMode.Zeros,
Mode = System.Security.Cryptography.CipherMode.CBC
};
using (var fsSource = new System.IO.FileStream(inputFile, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
using (var cs = new System.Security.Cryptography.CryptoStream(fs, aes.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write))
{
var readBytes = new byte[BLOCK_SIZE];
int read;
while ((read = fsSource.Read(readBytes, 0, BLOCK_SIZE)) != 0)
{
cs.Write(readBytes, 0, read);
}
cs.Close();
}
fsSource.Close();
}
fs.Close();
}
// Now add it to the archive
using (var p = part.GetStream(System.IO.FileMode.OpenOrCreate))
{
using (var source = new System.IO.FileStream(intermediateFile, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (var bw = new System.IO.BinaryWriter(p))
{
var readBytes = new byte[BLOCK_SIZE];
int read;
while ((read = source.Read(readBytes, 0, BLOCK_SIZE)) != 0)
{
bw.Write(readBytes.Take(read).ToArray());
}
}
}
// Clean up the intermediate
System.IO.File.Delete(intermediateFile);
}
}
}
}
压缩通常应该在加密之前完成,因为它通常可以获得更高的压缩比。(当然,这取决于数据类型。)显然这并不总是可能的,但可能对您来说是这样。那么您的目标是先加密文件,然后将其存储在zip中吗?您是使用zip进行存档还是压缩?两件事:-使用zip.PartExists而不是try-catch块-这样做成本不必要-一次1字节也很高-最好使用4096块并降低搅动,尤其是在查看10GB文件时。谢谢,Mark。我认为,在大多数情况下,这是最好的方法。但是有没有什么解决方案可以完全在内存中完成,而不需要临时文件呢?我相信你可以,但是内存成本会非常高。在这个场景中,我的页面文件在写入zip文件之间运行了大约500MB,正如我所提到的,对于3.8GB的ISO,它增长到了大约5GB。我不确定您正在加密/打包哪种数据,但我强烈建议您在文件流中使用辅助存储,而不是基于您所描述的内存流。在上面的场景中,您可以使用System.IO.MemoryStream替换可写文件流,但成本将非常高-并且您可能会面临缓冲区溢出的风险,这取决于您可以使用的内存。是否需要此操作的进一步信息,或者您是否同意我的回答?抱歉,我不在办公室,无法访问Internet。感谢您的时间,但这是我的目标-加载大文件并在内存中加密。我不想使用临时文件,因为这意味着我总共需要三个文件-第一个是原始文件,第二个是临时文件,第三个是输出文件。我的内存和磁盘空间有限。有什么办法吗?