我想使用对称算法加密和解密文件。对于小文件没有问题,但如果我们的文件很大(例如100 mb,1 GB,5 GB,...)简单的代码不起作用,我们必须使用不同的方法来解决这个问题。 我使用 ChatGPT 创建加密和解密方法,加密方法工作正常,读取大文件没有问题,并在磁盘上加密和写入加密文件。但是当我想解密文件时,我在 CryptographicEngine.Decrypt 行中收到 Com 异常。 我测试了一个 3 kb 的小文本文件,并且存在问题。 所以我发现如果加密文件出错解密就会失败。 那么我的加密方法有什么问题呢?如何解决这个问题?
public static async Task EncryptFileAsync(string inputFile, string outputFile)
{
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var keyMaterial = CryptographicBuffer.GenerateRandom(provider.BlockLength);
var iv = CryptographicBuffer.GenerateRandom(provider.BlockLength);
var key = provider.CreateSymmetricKey(keyMaterial);
const int bufferSize = 4096; // Choose an appropriate buffer size
var file = await StorageFile.GetFileFromPathAsync(inputFile);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
{
using (IInputStream inputStream = stream.GetInputStreamAt(0))
{
using (DataReader dataReader = new DataReader(inputStream))
{
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
while (stream.Position < stream.Size)
{
dataReader.InputStreamOptions = InputStreamOptions.Partial;
uint bytesRead = await dataReader.LoadAsync(bufferSize);
if (bytesRead > 0)
{
// Convert the buffer to IBuffer
IBuffer buffer = dataReader.ReadBuffer(bytesRead);
IBuffer bufferEncrypt = CryptographicEngine.Encrypt(key, buffer, iv);
var byteArray = bufferEncrypt.ToArray();
await fs.WriteAsync(byteArray, 0, byteArray.Length);
// Your processing logic with the IBuffer goes here
}
else
{
// Break the loop if no more bytes can be read
break;
}
}
}
}
}
}
// Save the key and iv for later decryption
SaveKeyAndIV(keyMaterial, iv);
}
public static async Task DecryptFileAsync(string inputFile, string outputFile)
{
// Load the key and iv used for encryption
var (keyMaterial, iv) = LoadKeyAndIV();
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
const int bufferSize = 4096; // Choose an appropriate buffer size
var file = await StorageFile.GetFileFromPathAsync(inputFile);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
{
using (IInputStream inputStream = stream.GetInputStreamAt(0))
{
using (DataReader dataReader = new DataReader(inputStream))
{
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
while (stream.Position < stream.Size)
{
dataReader.InputStreamOptions = InputStreamOptions.Partial;
uint bytesRead = await dataReader.LoadAsync(bufferSize);
if (bytesRead > 0)
{
// Convert the buffer to IBuffer
IBuffer buffer = dataReader.ReadBuffer(bytesRead);
IBuffer bufferDecrypt = CryptographicEngine.Decrypt(key, buffer, iv);
// Convert the decrypted buffer to byte array
var decryptedBytes = bufferDecrypt.ToArray();
await fs.WriteAsync(decryptedBytes, 0, decryptedBytes.Length);
// Your processing logic with the decrypted data goes here
}
else
{
// Break the loop if no more bytes can be read
break;
}
}
}
}
}
}
}
当您在部分代码周围放置“try catch 块”时,您可以更清楚地找出错误来自何处。这就是 它们在 C# 中的工作方式。
对于加密方法:
public static async Task EncryptFileAsync(string inputFile, string outputFile)
{
try
{
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var keyMaterial = CryptographicBuffer.GenerateRandom(provider.BlockLength);
var iv = CryptographicBuffer.GenerateRandom(provider.BlockLength);
var key = provider.CreateSymmetricKey(keyMaterial);
const int bufferSize = 4096; // Choose an appropriate buffer size
var file = await StorageFile.GetFileFromPathAsync(inputFile);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
{
using (IInputStream inputStream = stream.GetInputStreamAt(0))
{
using (DataReader dataReader = new DataReader(inputStream))
{
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
while (stream.Position < stream.Size)
{
dataReader.InputStreamOptions = InputStreamOptions.Partial;
uint bytesRead = await dataReader.LoadAsync(bufferSize);
if (bytesRead > 0)
{
IBuffer buffer = dataReader.ReadBuffer(bytesRead);
IBuffer bufferEncrypt = CryptographicEngine.Encrypt(key, buffer, iv);
var byteArray = bufferEncrypt.ToArray();
await fs.WriteAsync(byteArray, 0, byteArray.Length);
}
else
{
break;
}
}
}
}
}
}
SaveKeyAndIV(keyMaterial, iv);
}
catch (Exception ex)
{
// Handle the exception
Console.WriteLine($"Encryption failed with exception: {ex.Message}");
}
}
解密方法:
public static async Task DecryptFileAsync(string inputFile, string outputFile)
{
try
{
var (keyMaterial, iv) = LoadKeyAndIV();
var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesCbcPkcs7);
var key = provider.CreateSymmetricKey(keyMaterial);
const int bufferSize = 4096; // Choose an appropriate buffer size
var file = await StorageFile.GetFileFromPathAsync(inputFile);
using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
{
using (IInputStream inputStream = stream.GetInputStreamAt(0))
{
using (DataReader dataReader = new DataReader(inputStream))
{
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 4096, useAsync: true))
{
while (stream.Position < stream.Size)
{
dataReader.InputStreamOptions = InputStreamOptions.Partial;
uint bytesRead = await dataReader.LoadAsync(bufferSize);
if (bytesRead > 0)
{
IBuffer buffer = dataReader.ReadBuffer(bytesRead);
IBuffer bufferDecrypt = CryptographicEngine.Decrypt(key, buffer, iv);
var decryptedBytes = bufferDecrypt.ToArray();
await fs.WriteAsync(decryptedBytes, 0, decryptedBytes.Length);
}
else
{
break;
}
}
}
}
}
}
}
catch (Exception ex)
{
// Handle the exception
Console.WriteLine($"Decryption failed with exception: {ex.Message}");
}
}