ASP.NET Core 8.0 - AES Cipher

This article will describe the implementation of the AES Cipher utility. You should review the earlier articles of the Cookies And Claims Project series. Registered users can download the ASP.NET Core 8.0 - Cookies And Claims Project for free.

Cookies And Claims Project and Article Series

Free project download for registered users!

I developed the Cookies And Claims Project (CACP) to demonstrate a simple cookie authentication scheme and claim-based authorization with a clear and modifiable design. The CACP is developed with Visual Studio 2022 and the MS Long Term Support (LTS) version .NET 8.0 framework. All Errors, Warnings, and Messages from Code Analysis have been mitigated. The CACP implements utilities like an AES Cipher, Password Hasher, native JavaScript client form validation, password requirements UI, Bootstrap Native message modal generator, loading/spinner generator, SignalR online user count, and an automatic idle logout for users with administration permissions.

The CACP implements a group of utilities: AES Cipher, Password Hasher, Password Validation, Message Generator, and Spinner Generator. This article describes the AES Cipher. The utility is implemented with an AesCrypto class. The AesCrypto class can generate new 128, 192, and 256 bit random keys as Base64 or Hexadecimal strings. The Encrypt and Decrypt methods include key, initialization vector, key size, and format parameters. My premium projects use the AesCrypto class to decrypt the encrypted SQL Server ConnectionStrings stored in appsettings.json. See ASP.NET Core 5.0 - AppSettings Encryption.

AesCrypto.cs:
// Copyright © Ken Haggerty (https://kenhaggerty.com)
// Licensed under the MIT License.
namespace CookiesAndClaims.Services;
public static class AesCrypto
{
    /// <summary>
    /// Generates a new random key.
    /// </summary>
    /// <param name="keyByteSize">Key size in bytes.</param>
    /// <param name="useHex">Use Hexadecimal format.</param>
    /// <returns>
    /// A Base64 or Hexadecimal string representing a byte array of random values.
    /// </returns>
    /// <remarks>
    /// The AES Key can be 128 bits = 16 bytes, 192 bits = 24 bytes or 256 bits = 32 bytes.
    /// </remarks>
    /// <exception cref="ArgumentNullException"></exception>
    public static string GetNewRandom(int keyByteSize = 16, bool useHex = false)
    {
        byte[] randomArray = new byte[keyByteSize];
        using var rng = RandomNumberGenerator.Create();
        rng.GetBytes(randomArray);

        if (useHex)
            return BitConverter.ToString(randomArray).Replace("-", "");
        else
            return Convert.ToBase64String(randomArray);
    }

    /// <summary>
    /// Encrypts plain text using the key and initialization vector (iv).
    /// </summary>
    /// <param name="key">The key in Base64 or Hexadecimal string format.</param>
    /// <param name="iv">The initialization vector (iv) in Base64 or Hexadecimal string format.</param>
    /// <param name="plainText">The text to be encrypted.</param>
    /// <param name="keyByteSize">Key size in bytes.</param>
    /// <param name="useHex">Use Hexadecimal format for key and iv.</param>
    /// <returns>
    /// A string AES encrypted using the key and initialization vector (iv).
    /// </returns>
    /// <remarks>
    /// The AES Key can be 128 bits = 16 bytes, 192 bits = 24 bytes or 256 bits = 32 bytes.
    /// </remarks>
    /// <exception cref="ArgumentException"></exception>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    /// <exception cref="FormatException"></exception>
    /// <exception cref="OverflowException"></exception>
    /// <exception cref="ObjectDisposedException"></exception>
    /// <exception cref="NotSupportedException"></exception>
    /// <exception cref="IOException"></exception>
    public static string EncryptString(string key, string iv, string plainText, int keyByteSize = 16, bool useHex = false)
    {
        byte[] keyBytes = new byte[keyByteSize];
        byte[] ivBytes = new byte[16];
        byte[] cipherBytes;

        if (useHex)
        {
            int len = keyByteSize * 2;
            for (int i = 0; i < len; i += 2)
            {
                keyBytes[i / 2] = Convert.ToByte(key.Substring(i, 2), 16);
                if (i < 32)
                    ivBytes[i / 2] = Convert.ToByte(iv.Substring(i, 2), 16);
            }
        }
        else
        {
            keyBytes = Convert.FromBase64String(key);
            ivBytes = Convert.FromBase64String(iv);
        }

        using Aes aes = Aes.Create();
        aes.Key = keyBytes;
        aes.IV = ivBytes;
        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        using MemoryStream memoryStream = new MemoryStream();
        using CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
        using (StreamWriter streamWriter = new StreamWriter(cryptoStream))
        {
            streamWriter.Write(plainText);
        }
        cipherBytes = memoryStream.ToArray();
        return Convert.ToBase64String(cipherBytes);
    }

    /// <summary>
    /// Decrypts cipher text using the key and initialization vector (iv).
    /// </summary>
    /// <param name="key">The key in Base64 or Hexadecimal string format.</param>
    /// <param name="iv">The initialization vector (iv) in Base64 or Hexadecimal string format.</param>
    /// <param name="cipherText">The encrypted text.</param>
    /// <param name="keyByteSize">Key size in bytes.</param>
    /// <param name="useHex">Use Hexadecimal format for key and iv.</param>
    /// <returns>
    /// A string AES decrypted using the key and initialization vector (iv).
    /// </returns>
    /// <remarks>
    /// The AES Key can be 128 bits = 16 bytes, 192 bits = 24 bytes or 256 bits = 32 bytes.
    /// </remarks>
    /// <exception cref="ArgumentException"></exception>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    /// <exception cref="FormatException"></exception>
    /// <exception cref="OverflowException"></exception>
    /// <exception cref="OutOfMemoryException"></exception>
    /// <exception cref="IOException"></exception>
    public static string DecryptString(string key, string iv, string cipherText, int keyByteSize = 16, bool useHex = false)
    {
        byte[] keyBytes = new byte[keyByteSize];
        byte[] ivBytes = new byte[16];
        byte[] cipherBytes = Convert.FromBase64String(cipherText);

        if (useHex)
        {
            int len = keyByteSize * 2;
            for (int i = 0; i < len; i += 2)
            {
                keyBytes[i / 2] = Convert.ToByte(key.Substring(i, 2), 16);
                if (i < 32)
                    ivBytes[i / 2] = Convert.ToByte(iv.Substring(i, 2), 16);
            }
        }
        else
        {
            keyBytes = Convert.FromBase64String(key);
            ivBytes = Convert.FromBase64String(iv);
        }

        using Aes aes = Aes.Create();
        aes.Key = keyBytes;
        aes.IV = ivBytes;
        ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        using MemoryStream memoryStream = new MemoryStream(cipherBytes);
        using CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
        using StreamReader streamReader = new StreamReader(cryptoStream);
        return streamReader.ReadToEnd();
    }
}
AES Cipher.
Ken Haggerty
Created 10/24/24
Updated 10/24/24 20:47 GMT

Log In or Reset Quota to read more.

Successfully completed. Thank you for contributing.
Processing...
Something went wrong. Please try again.
Contribute to enjoy content without advertisments.
You can contribute without registering.

Comments(0)

Loading...
Loading...

Not accepting new comments.

Submit your comment. Comments are moderated.

User Image.
DisplayedName - Member Since ?