简体   繁体   English

AES 256 文件加密 c#

[英]AES 256 file encryption c#

I can't seem to find a nice clean example of using AES 256 encryption for encrypting a file in c#我似乎找不到使用 AES 256 加密在 c# 中加密文件的干净示例

Does anyone have some sample code?有人有一些示例代码吗?

Here is the asnwer to above question这是上述问题的答案

 UnicodeEncoding ue = new UnicodeEncoding();

                byte[] key = ue.GetBytes(password);
                string cryptFile = outputFile;
                using (FileStream fileCrypt = new FileStream(cryptFile, FileMode.Create))
                {
                    using (AesManaged encrypt = new AesManaged())
                    {
                        using (CryptoStream cs = new CryptoStream(fileCrypt, encrypt.CreateEncryptor(key, key), CryptoStreamMode.Write))
                        {
                            using (FileStream fileInput = new FileStream(inputFile, FileMode.Open))
                            {
                                encrypt.KeySize = 256;
                                encrypt.BlockSize = 128;
                                int data;
                                while ((data = fileInput.ReadByte()) != -1)
                                    cs.WriteByte((byte)data);
                            }
                        }
                    }
                }

I'm no security expert, and I haven't tested this except with small files, but here's my modernized and complete version of AES-256 file encryption using .NET 6:我不是安全专家,除了小文件外,我没有对此进行过测试,但这是我使用 .NET 6 进行的 AES-256 文件加密的现代化和完整版本:

using System.Security.Cryptography;
using System.Text;

namespace Core.Encryption;

/// <summary>
/// Encrypts and decrypts files using AES-256.
/// String keys are encoded using UTF8.
/// </summary>
public static class FileEncryptor
{
    private const int AesKeySize = 256;
    private const int AesBlockSize = 128;

    public const int KeySizeInBytes = AesKeySize / 8;

    /// <summary>
    /// Encrypts a file using a 32 character key.
    /// </summary>
    public static Task EncryptAsync(string inputFilePath, string outputFilePath, string key, CancellationToken token = default)
    {
        if (string.IsNullOrWhiteSpace(key))
        {
            throw new ArgumentException("Key cannot be empty!", nameof(key));
        }

        byte[] keyBytes = Encoding.UTF8.GetBytes(key);
        return EncryptAsync(inputFilePath, outputFilePath, keyBytes, token);
    }

    public static async Task EncryptAsync(string inputFilePath, string outputFilePath, byte[] keyBytes, CancellationToken token = default)
    {
        if (!File.Exists(inputFilePath))
        {
            throw new ArgumentException("Input file does not exist!", nameof(inputFilePath));
        }

        if (keyBytes.Length != KeySizeInBytes)
        {
            throw new ArgumentException("Key must be 32 bytes (256 bits) in length!", nameof(keyBytes));
        }

        using var aes = Aes.Create();
        aes.BlockSize = AesBlockSize;
        aes.KeySize = AesKeySize;
        aes.Key = keyBytes;

        await using FileStream outFileStream = new(outputFilePath, FileMode.Create);

        // Write initialization vector to beginning of file
        await outFileStream.WriteAsync(aes.IV.AsMemory(0, aes.IV.Length), token);

        ICryptoTransform encryptor = aes.CreateEncryptor();
        await using CryptoStream cryptoStream = new(
            outFileStream,
            encryptor,
            CryptoStreamMode.Write);

        await using var inputFileStream = new FileStream(inputFilePath, FileMode.Open);

        await inputFileStream.CopyToAsync(cryptoStream, token);
    }

    /// <summary>
    /// Decrypts a file using a 32 character key.
    /// </summary>
    public static Task DecryptAsync(string inputFilePath, string outputFilePath, string key, CancellationToken token = default)
    {
        if (string.IsNullOrWhiteSpace(key))
        {
            throw new ArgumentException("Key cannot be empty!", nameof(key));
        }

        byte[] keyBytes = Encoding.UTF8.GetBytes(key);
        return DecryptAsync(inputFilePath, outputFilePath, keyBytes, token);
    }

    public static async Task DecryptAsync(string inputFilePath, string outputFilePath, byte[] keyBytes, CancellationToken token = default)
    {
        if (!File.Exists(inputFilePath))
        {
            throw new ArgumentException("Input file does not exist!", nameof(inputFilePath));
        }

        if (keyBytes.Length != KeySizeInBytes)
        {
            throw new ArgumentException("Key must be 32 bytes (256 bits) in length!", nameof(keyBytes));
        }

        await using var inputFileStream = new FileStream(inputFilePath, FileMode.Open);

        // Read IV from beginning of file
        const int blockSizeInBytes = AesBlockSize / 8;
        var initializationVector = new byte[blockSizeInBytes];
        int ivBytesRead = await inputFileStream.ReadAsync(initializationVector.AsMemory(0, blockSizeInBytes), token);

        if (ivBytesRead != initializationVector.Length)
        {
            throw new ArgumentException("Failed to read initialization vector from input file!", nameof(inputFilePath));
        }

        using var aes = Aes.Create();
        aes.BlockSize = AesBlockSize;
        aes.IV = initializationVector;
        aes.KeySize = AesKeySize;
        aes.Key = keyBytes;

        ICryptoTransform decryptor = aes.CreateDecryptor();
        await using CryptoStream cryptoStream = new(
            inputFileStream,
            decryptor,
            CryptoStreamMode.Read);

        await using FileStream outFileStream = new(outputFilePath, FileMode.Create);
        await cryptoStream.CopyToAsync(outFileStream, token);
    }
}

I also haven't tested cancellation, but I don't see why it shouldn't work.我也没有测试取消,但我不明白为什么它不应该工作。 It goes without saying that you should do your own tests :-)不用说,您应该进行自己的测试 :-)

Usage:用法:

var inputFile = @"C:\tmp\test.txt";
var outputFile = @"C:\tmp\test.encrypted";
var password = "abcde-fghij-klmno-pqrst-uvwxy-z0"; // must be 32 chars (256 / 8 = 32 bytes)

await FileEncryptor.EncryptAsync(inputFile, outputFile, password);
await FileEncryptor.DecryptAsync(outputFile, @"C:\tmp\decrypted.txt", password);

To support multiple key sizes, I suppose we could write it to the start of the file just like the IV, but for my requirements this was enough.为了支持多种密钥大小,我想我们可以像 IV 一样将它写入文件的开头,但对于我的要求,这已经足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM