Encryption and Decryption using AES in .NET Core and .NET Framework

Introduction

AES is a symmetric key algorithm, meaning the same key is used for both encryption and decryption. This is in contrast to asymmetric encryption, where a public key is used for encryption and a private key for decryption.

Encryption

Step 1

using (var rijndaelManaged = new RijndaelManaged { Key = cryptkey, IV = initVector, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7, KeySize = 128 })
  • RijndaelManaged: This is a class provided by the .NET framework to perform AES encryption.
  • Key: The crypt key is the encryption key used. It must be 128, 192, or 256 bits long (16, 24, or 32 bytes).
  • IV: initVector is the initialization vector, which is used to add randomness to the encryption process.
  • Mode = CipherMode.CBC: Sets the mode of operation to Cipher Block Chaining (CBC). This means each block of plaintext is XORed with the previous ciphertext block before being encrypted.
  • Padding = PaddingMode.PKCS7: Specifies the padding scheme to ensure the data length is compatible with the block size of the cipher.
  • KeySize = 128: The size of the encryption key in bits (128 bits in this case).

Step 2

using (var memoryStream = new MemoryStream())

MemoryStream: This is a stream in memory where the encrypted bytes will be written.

Step 3

using (var cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(cryptkey, initVector), CryptoStreamMode.Write))
  • CryptoStream: This stream links data streams to cryptographic transformations. Here, it wraps the MemoryStream.
  • CreateEncryptor(cryptkey, initVector): Creates a symmetric encryptor object using the provided key and IV.
  • CryptoStreamMode.Write: Specifies that the stream will be used for writing.

Step 4

using (var ws = new StreamWriter(cryptoStream))
{
    ws.Write(textToCrypt);
}

StreamWriter: This class is used to write characters to a stream. It writes the plaintext textToCrypt to the CryptoStream, which automatically encrypts it and writes the result to the MemoryStream.

Step 5

return Convert.ToBase64String(memoryStream.ToArray());

The encrypted bytes stored in the MemoryStream are converted to a Base64 string, which is returned as the result of the encryption process.

Completed Encryption Method

public string EncryptAES(string textToCrypt)
{
   private  byte[] cryptkey = Encoding.ASCII.GetBytes("1234567891234567");
   private  byte[] initVector = Encoding.ASCII.GetBytes("1234567891234567");
    try
    {
        using (var rijndaelManaged =
               new RijndaelManaged { Key = cryptkey, IV = initVector, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7, KeySize = 128 })
        using (var memoryStream = new MemoryStream())
        using (var cryptoStream =
               new CryptoStream(memoryStream,
                   rijndaelManaged.CreateEncryptor(cryptkey, initVector),
                   CryptoStreamMode.Write))
        {
            using (var ws = new StreamWriter(cryptoStream))
            {
                ws.Write(textToCrypt);
            }
            return Convert.ToBase64String(memoryStream.ToArray());
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
        return null;
    }
}

Sample Output

Output

Decryption Complete Method

  public string DecryptAES(string cipherData)
  {
      try
      {
          using (var rijndaelManaged =
                 new RijndaelManaged { Key = cryptkey, IV = initVector, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7, KeySize = 128 })
          using (var memoryStream =
                 new MemoryStream(Convert.FromBase64String(cipherData)))
          using (var cryptoStream =
                 new CryptoStream(memoryStream,
                     rijndaelManaged.CreateDecryptor(cryptkey, initVector),
                     CryptoStreamMode.Read))
          {
              return new StreamReader(cryptoStream).ReadToEnd();
          }
      }
      catch (CryptographicException e)
      {
          Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
          return null;
      }
  }

Sample Output for Decryption

Decryption

Different options for AES

  1. KeySize
    • 192 bits: You could use KeySize = 192 for increased security.
    • 256 bits: KeySize = 256 provides the highest level of security but with a potential impact on performance.
    • KeySize = 128: Specifies that the key size is 128 bits.
  2. Padding
    • PaddingMode.None: No padding is added. You must ensure the plaintext length is a multiple of the block size.
    • PaddingMode.Zeros: Pads with zeros. However, if the plaintext ends with zero bytes, it may cause ambiguity during decryption.
    • PaddingMode.ANSIX923: Pads with zeros followed by a byte that indicates the number of padding bytes.
    • PaddingMode.ISO10126: Pads with random bytes followed by a byte that indicates the number of padding bytes.
    • PaddingMode.PKCS7: Padding is used to make the plaintext a multiple of the block size. PKCS7 is a common padding scheme that appends bytes to the end of the plaintext, where each byte's value indicates the number of padding bytes added.
  3. Mode
    • CipherMode.ECB: Electronic Codebook (ECB) mode encrypts each block of plaintext independently. This mode is less secure because identical plaintext blocks will result in identical ciphertext blocks.
    • CipherMode.CFB: Cipher Feedback (CFB) mode turns a block cipher into a stream cipher, allowing data to be encrypted in smaller chunks.
    • CipherMode.OFB: Output Feedback (OFB) mode also converts a block cipher into a stream cipher and avoids error propagation.
    • CipherMode.CTS: Cipher Text Stealing (CTS) mode is used to handle plaintext data that is not a multiple of the block size without padding.
    • CipherMode.CBC: Cipher Block Chaining (CBC) mode is a common mode of operation for block ciphers. Each block of plaintext is XORed with the previous ciphertext block before being encrypted.

Conclusion

where you define the encryption key, initialization vector (IV), cipher mode, padding mode, and key size. Each of these options plays a crucial role in determining the security and behavior of the encryption process. You can customize these settings based on your specific security needs, balancing factors like security strength, performance, and compatibility.