我的目标是加密大型(cca 10 GB)输入文件并将其附加到现有的System.IO.Packaging包。我只能使用.NET Framework 3.5而不能使用第三方库。
我尝试了十种方法但没有成功。我尝试读取Stream的输入,加密并保存到PackagePart。我尝试逐字节读取输入文件,然后加密字节读取并将其从PackagePart附加到Stream。每次我发现一个新问题(例如CryptoStream不支持搜索等)。
你能告诉我正确的方法吗?
//method to create zip file (just a sample)
public static void AppendToZip(SomeType encryptedData)
{
using (Package zip = Package.Open(@"C:\myarchive.zip", FileMode.OpenOrCreate))
{
Uri uri = PackUriHelper.CreatePartUri(new Uri("/files/test.enc", UriKind.Relative));
try
{
part = zip.GetPart(uri);
}
catch
{
}
if (part == null)
{
part = zip.CreatePart(uri, "", CompressionOption.Maximum);
}
using (Stream dest = part.GetStream())
{
//how to write encryptedData to destination stream?
}
}
}
//sample method for encrypting a file
private static void Encrypt(string inputFile, string cryptFile, byte[] passwordBytes, byte[] saltBytes)
{
FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create);
RijndaelManaged AES = new RijndaelManaged();
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Padding = PaddingMode.Zeros;
AES.Mode = CipherMode.CBC;
CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write);
FileStream fsIn = new FileStream(inputFile, FileMode.Open);
int data;
while ((data = fsIn.ReadByte()) != -1)
{
cs.WriteByte((byte)data);
}
fsIn.Close();
cs.Close();
fsCrypt.Close();
}
答案 0 :(得分:2)
尝试这一点 - 玩块大小以获得性能。我成功地使用了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);
}
}
}
}