使用对称算法加密和解密文件

问题描述 投票:0回答:1

我想使用对称算法加密和解密文件。对于小文件没有问题,但如果我们的文件很大(例如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;
                        }
                    }
                }
            }
        }
    }
}
c# .net winui-3 encryption-symmetric
1个回答
0
投票

当您在部分代码周围放置“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}");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.