简体   繁体   中英

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#

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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