.NET HELP

C# AES Encryption (How It Works For Developers)

Kannaopat Udonpant
Kannapat Udonpant
October 23, 2024
Share:

AES (Advanced Encryption Standard) is one of the most commonly used symmetric encryption algorithms. It uses the same key to encrypt and decrypt data, making AES encryption efficient and fast for securing sensitive data in many applications.

This tutorial will focus on AES encryption in C#, using the AES class to encrypt and decrypt data and IronPDF Library. We’ll cover practical examples, walk through the encryption process, and see how to use Cipher Block Chaining (CBC) mode to increase security. We’ll also discuss encryption key management and the role of the initialization vector (IV).

Introduction of AES Encryption in C#

Advanced Encryption Standard (AES) is a symmetric encryption algorithm standardized by the National Institute of Standards and Technology (NIST). The algorithm can have key sizes of 128, 192, or 256 bits and is highly secure for encrypting confidential data. It uses the same encryption key to encrypt and decrypt data.

AES works by splitting the original data into blocks and applying transformations on those blocks. It operates in different cipher modes, such as CBC (Cipher Block Chaining) and Electronic CodeBook (ECB), each providing different security features.

How AES Works in C#

The AES encryption algorithm in C# is part of the System.Security.Cryptography namespace. This namespace includes the AES class, which allows us to create an instance of AES, specify the key size, cipher mode, and padding mode, and then encrypt and decrypt data using a secret key.

To use AES in C#, follow these basic steps:

  1. Create an instance of the AES class using Aes.Create().
  2. Set the key, IV, and other relevant parameters like cipher mode.
  3. Encrypt the data using the ICryptoTransform interface and write it to a MemoryStream.
  4. Decrypt the data using the same key and IV.

Let’s create a basic encryption process and decryption program in C#.

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
class Program
{
    // Declare a static byte array for encrypted data
    public static byte[] encryptedData;
    // static void Main
    public static void Main(string[] args)
    {
        // string plaintext to be encrypted
        string plaintext = "This is some sensitive data!";
        string key = "abcdefghijklmnop"; // 128-bit key (16 characters)
        // Encrypt the plaintext
        string ciphertext = Encrypt(plaintext, key);
        Console.WriteLine("Encrypted Data: " + ciphertext);
        // Decrypt the ciphertext
        string decryptedData = Decrypt(ciphertext, key);
        Console.WriteLine("Decrypted Data: " + decryptedData);
    }
    public static string Encrypt(string plaintext, string key)
    {
        // AES algorithm
        using (Aes aes = Aes.Create())
        {
            aes.Key = Encoding.UTF8.GetBytes(key);
            aes.IV = new byte[16]; // Initialization vector (IV)
            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter sw = new StreamWriter(cs))
                    {
                        sw.Write(plaintext);
                    }
                }
                // Store the encrypted data in the public static byte array
                encryptedData = ms.ToArray();
                return Convert.ToBase64String(encryptedData);
            }
        }
    }
    public static string Decrypt(string ciphertext, string key)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = Encoding.UTF8.GetBytes(key);
            aes.IV = new byte[16]; // Initialization vector (IV)
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(ciphertext)))
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader sr = new StreamReader(cs))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
        }
    }
}
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
class Program
{
    // Declare a static byte array for encrypted data
    public static byte[] encryptedData;
    // static void Main
    public static void Main(string[] args)
    {
        // string plaintext to be encrypted
        string plaintext = "This is some sensitive data!";
        string key = "abcdefghijklmnop"; // 128-bit key (16 characters)
        // Encrypt the plaintext
        string ciphertext = Encrypt(plaintext, key);
        Console.WriteLine("Encrypted Data: " + ciphertext);
        // Decrypt the ciphertext
        string decryptedData = Decrypt(ciphertext, key);
        Console.WriteLine("Decrypted Data: " + decryptedData);
    }
    public static string Encrypt(string plaintext, string key)
    {
        // AES algorithm
        using (Aes aes = Aes.Create())
        {
            aes.Key = Encoding.UTF8.GetBytes(key);
            aes.IV = new byte[16]; // Initialization vector (IV)
            ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter sw = new StreamWriter(cs))
                    {
                        sw.Write(plaintext);
                    }
                }
                // Store the encrypted data in the public static byte array
                encryptedData = ms.ToArray();
                return Convert.ToBase64String(encryptedData);
            }
        }
    }
    public static string Decrypt(string ciphertext, string key)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = Encoding.UTF8.GetBytes(key);
            aes.IV = new byte[16]; // Initialization vector (IV)
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(ciphertext)))
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader sr = new StreamReader(cs))
                    {
                        return sr.ReadToEnd();
                    }
                }
            }
        }
    }
}

C# AES Encryption (How It Works For Developers): Figure 1 - Encryption and Decryption Output using Memory Stream

Explanation of Code

  1. Aes aes = Aes.Create(): This creates a new instance of the AES encryption algorithm.
  2. Aes.Key: The key used for both encryption and decryption. It must be of a valid size, such as 128 bits (16 bytes), 192 bits, or 256 bits.
  3. Aes.IV: The initialization vector (IV), is used to randomize the encryption process. In this example, we use an IV of zeros for simplicity.
  4. MemoryStream: This allows us to work with the encrypted data as a stream of bytes.
  5. CryptoStream: It transforms the data stream (encryption or decryption).

Advanced Example: AES Encryption with Custom Key and IV

Let’s build upon the previous example by generating a random key and IV, ensuring the encryption is more secure.

public static string EncryptData(string plaintext)
{
    using (Aes aes = Aes.Create())
    {
        aes.Key = new byte[32]; // AES-256 requires a 256-bit key (32 bytes)
        aes.IV = new byte[16];  // 128-bit block size
        using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(aes.Key); // Generate a random key
            rng.GetBytes(aes.IV);  // Generate a random IV
        }
        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter sw = new StreamWriter(cs))
                {
                    sw.Write(plaintext);
                }
            }
            return Convert.ToBase64String(ms.ToArray());
        }
    }
}
public static string EncryptData(string plaintext)
{
    using (Aes aes = Aes.Create())
    {
        aes.Key = new byte[32]; // AES-256 requires a 256-bit key (32 bytes)
        aes.IV = new byte[16];  // 128-bit block size
        using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
        {
            rng.GetBytes(aes.Key); // Generate a random key
            rng.GetBytes(aes.IV);  // Generate a random IV
        }
        ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            {
                using (StreamWriter sw = new StreamWriter(cs))
                {
                    sw.Write(plaintext);
                }
            }
            return Convert.ToBase64String(ms.ToArray());
        }
    }
}

In this case, we generate a new key and IV each time the function is called. This provides more robust encryption as the same key is unused for every operation. AES supports key sizes such as 128, 192, and 256 bits.

Decrypting Data with AES

Decryption is the reverse process to encrypt data. In our examples, the same key and IV used for encryption must be provided to decrypt the data. The decryption process involves converting the encrypted data back into its original form.

Here’s an example that uses the previously encrypted data:

public static string DecryptData(string ciphertext, byte[] key, byte[] iv)
{
    using (Aes aes = Aes.Create())
    {
        aes.Key = key;
        aes.IV = iv;
        ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(ciphertext)))
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader sr = new StreamReader(cs))
                {
                    return sr.ReadToEnd();
                }
            }
        }
    }
}
public static string DecryptData(string ciphertext, byte[] key, byte[] iv)
{
    using (Aes aes = Aes.Create())
    {
        aes.Key = key;
        aes.IV = iv;
        ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
        using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(ciphertext)))
        {
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader sr = new StreamReader(cs))
                {
                    return sr.ReadToEnd();
                }
            }
        }
    }
}

This code decrypts the encrypted data back into the original data.

IronPDF with AES Encryption

IronPDF is a simple and developer-friendly .NET library designed to generate, edit, and manipulate PDFs using simple C# code. It allows developers to create PDF documents directly from HTML, CSS, and JavaScript, which can be incredibly useful for dynamically generating reports, invoices, or other documents. With support for merging, splitting, and even adding security features like passwords or digital signatures, IronPDF is a comprehensive solution for PDF generation in .NET applications.

Integrating IronPDF with AES Encryption

C# AES Encryption (How It Works For Developers): Figure 2 - IronPDF

When you generate sensitive reports or documents, you may need to ensure the data within those PDFs is encrypted before sharing. AES (Advanced Encryption Standard) encryption is a perfect solution for securely encrypting the contents of PDF files. By combining IronPDF and AES encryption, you can protect the data within your PDFs while maintaining the ability to work with the document itself.

Step 1: Create a PDF Using IronPDF

Use the ChromePdfRenderer class to generate a PDF from HTML content and save it to a file:

var htmlContent = "<h1>Confidential</h1><p>This is sensitive data.</p>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs(@"C:\Reports\ConfidentialReport.pdf");
var htmlContent = "<h1>Confidential</h1><p>This is sensitive data.</p>";
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs(@"C:\Reports\ConfidentialReport.pdf");

Step 2: Encrypt the PDF Using AES

Once the PDF is created, encrypt it with AES:

byte[] pdfBytes = File.ReadAllBytes(@"C:\Reports\ConfidentialReport.pdf");
using (Aes aes = Aes.Create())
{
    aes.Key = Encoding.UTF8.GetBytes("abcdefghijklmnop");
    aes.IV = new byte[16];
    using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
    using (var ms = new MemoryStream())
    {
        using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
        {
            cs.Write(pdfBytes, 0, pdfBytes.Length);
        }
        File.WriteAllBytes(@"C:\Reports\ConfidentialReport.encrypted", ms.ToArray());
    }
}
byte[] pdfBytes = File.ReadAllBytes(@"C:\Reports\ConfidentialReport.pdf");
using (Aes aes = Aes.Create())
{
    aes.Key = Encoding.UTF8.GetBytes("abcdefghijklmnop");
    aes.IV = new byte[16];
    using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
    using (var ms = new MemoryStream())
    {
        using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
        {
            cs.Write(pdfBytes, 0, pdfBytes.Length);
        }
        File.WriteAllBytes(@"C:\Reports\ConfidentialReport.encrypted", ms.ToArray());
    }
}

Conclusion

C# AES Encryption (How It Works For Developers): Figure 3 - Licensing

Integrating IronPDF with AES encryption allows you to generate dynamic, secure documents that are both accessible and encrypted. Whether developing applications requiring secure document generation or managing sensitive reports, combining IronPDF with solid encryption protects your data. IronPDF simplifies working with PDFs, while AES guarantees that the content remains secure.

IronPDF offers a free trial, making it easy for developers to explore its features before committing. If you’re ready to implement IronPDF into your projects, licenses start at $749 for a one-time purchase.

Kannaopat Udonpant
Software Engineer
Before becoming a Software Engineer, Kannapat completed a Environmental Resources PhD from Hokkaido University in Japan. While pursuing his degree, Kannapat also became a member of the Vehicle Robotics Laboratory, which is part of the Department of Bioproduction Engineering. In 2022, he leveraged his C# skills to join Iron Software's engineering team, where he focuses on IronPDF. Kannapat values his job because he learns directly from the developer who writes most of the code used in IronPDF. In addition to peer learning, Kannapat enjoys the social aspect of working at Iron Software. When he's not writing code or documentation, Kannapat can usually be found gaming on his PS5 or rewatching The Last of Us.
< PREVIOUS
C# try catch finally (How It Works For Developers)
NEXT >
C# HttpClient (How It Works For Developers)