AES with .NET

Introduction to AES

The AES encryption is a symmetric cipher and uses the same key for encryption and decryption. The AES algorithm supports 128, 192 and 256 bit encryption, which is determined from the key size : 128 bit encryption when the key is 16 bytes, 192 when the key is 24 bytes and 256 bit when the key is 32 bytes.

The methods provided by the library accept also a string password instead of a key, which is internally converted to a key with a chosen Hash function.

The optional initialization vector (IV) size is 16 bytes, which is the block size of the algorithm. This is summarized in the table below:

Key size AES encryption
16 bytes (128 bits) 128 bit encryption
24 bytes (192 bits) 192 bit encryption
32 bytes (256 bits) 256 bit encryption
IV size:16 bytes

Back to Top

Padding and Block modes

The Padding and Block mode are important settings for the AES class, that affect the produced encrypted output.

The Padding is used to align the input data to the algorithm BlockSize (16 bytes). The default is PKCS7.

The Block Mode determines what transformation is performed on each processed block. The default one is CBC. It is very important to know what block mode was used for encryption, in order to be able to decrypt it! For example if we know that the encryption has used CTR block mode, we shall set the class to use that mode before decrypting:

AES aes = new AES();
aes.Mode = CipherBlockMode.CTR;
aes.Decrypt...

Back to Top

AES encrypting and decrypting a String

The example below shows how to AES encrypt and decrypt a String with a byte array key, with a password and by using or not the optional initialization vector (IV).

using System;
using System.IO;
using NCiphers.Ciphers;

class AES_Demo
{
    public static void Main(string[] args)
    {
        AES aes = new AES();
        // 16 bytes long key for AES-128 bit encryption
        byte[] key = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230};
        // optional 16 byte long initialization vector
        byte[] IV = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106};

        string message = "Hello World";

        // encrypt with a key only
        string encryptedMessage = aes.EncryptString(message, key);
        // encrypt with a key and IV
        string encryptedMessageWithIV = aes.EncryptString(message, key, IV);
        // encrypt with a password
        string encryptedMessageWithPassword = aes.EncryptString(message, "my password");
        // encrypt with a password and IV
        string encryptedMessageWithPasswordAndIV = aes.EncryptString(message, "my password", IV);

        message = aes.DecryptString(encryptedMessage, key);
        message = aes.DecryptString(encryptedMessageWithIV, key, IV);
        message = aes.DecryptString(encryptedMessageWithPassword, "my password");
        message = aes.DecryptString(encryptedMessageWithPasswordAndIV, "my password", IV);
    }
}

 

Imports System
Imports System.IO
Imports NCiphers.Ciphers

Class AES_Demo
    Public Shared Sub Execute()
        Dim aes As New AES()

        ' 16 bytes long key for AES-128 bit encryption
        Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230}

        ' the 16 byte initialization vector is optional and can be skipped
        Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106}

        Dim message As String = "Hello World"

        Dim encryptedMessage As String = aes.EncryptString(message, key)
        Dim encryptedMessageWithIV As String = aes.EncryptString(message, key, IV)
        Dim encryptedMessageWithPassword As String = aes.EncryptString(message, "my password")
        Dim encryptedMessageWithPasswordAndIV As String = aes.EncryptString(message, "my password", IV)

        message = aes.DecryptString(encryptedMessage, key)
        message = aes.DecryptString(encryptedMessageWithIV, key, IV)
        message = aes.DecryptString(encryptedMessageWithPassword, "my password")
        message = aes.DecryptString(encryptedMessageWithPasswordAndIV, "my password", IV)
    End Sub
End Class

Back to Top

Encrypting and Decrypting a File

The file encryption is performed by calling the methods AES.EncryptFile. The decryption is through the DecryptFile methods respectively:

using System;
using System.IO;
using NCiphers.Ciphers;

class AES_Demo
{
    public static void Main(string[] args)
    {
        AES aes = new AES();
        // 16 bytes long key for AES-128 bit encryption
        byte[] key = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230};

        // the initialization vector is optional and can be skipped
        byte[] IV = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106};

        // AES Encrypting
        aes.EncryptFile(new FileInfo(@"Data\SampleFile.txt"), new FileInfo(@"Data\EncryptedFile.aes"), key);
        aes.EncryptFile(new FileInfo(@"Data\SampleFile.txt"), new FileInfo(@"Data\EncryptedFileWithIV.aes"), key, IV);
        aes.EncryptFile(new FileInfo(@"Data\SampleFile.txt"), new FileInfo(@"Data\EncryptedFileWithPassword.aes"), "my password");
        aes.EncryptFile(new FileInfo(@"Data\SampleFile.txt"), new FileInfo(@"Data\EncryptedFileWithPasswordAndIV.aes"), "my password", IV);

        // AES Decrypting
        aes.DecryptFile(new FileInfo(@"Data\EncryptedFile.aes"), new FileInfo(@"Data\Output.txt"), key);
        aes.DecryptFile(new FileInfo(@"Data\EncryptedFileWithIV.aes"), new FileInfo(@"Data\Output.txt"), key, IV);
        aes.DecryptFile(new FileInfo(@"Data\EncryptedFileWithPassword.aes"), new FileInfo(@"Data\Output.txt"), "my password");
        aes.DecryptFile(new FileInfo(@"Data\EncryptedFileWithPasswordAndIV.aes"), new FileInfo(@"Data\Output.txt"), "my password", IV);
    }
}

VB.NET example

Imports System
Imports System.IO
Imports NCiphers.Ciphers

Class AES_Demo
    Public Shared Sub Execute()
        Dim aes As New AES()
        ' 16 bytes long key for AES-128 bit encryption
        Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230}

        ' the 16 byte initialization vector is optional
        Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106}

        ' AES encrypting
        aes.EncryptFile(New FileInfo("Data\SampleFile.txt"), New FileInfo("Data\EncryptedFile.aes"), key)
        aes.EncryptFile(New FileInfo("Data\SampleFile.txt"), New FileInfo("Data\EncryptedWithIV.aes"), key)
        aes.EncryptFile(New FileInfo("Data\SampleFile.txt"), New FileInfo("Data\EncryptedWithPassword.aes"), key)
        aes.EncryptFile(New FileInfo("Data\SampleFile.txt"), New FileInfo("Data\EncryptedWithPasswordAndIV.aes"), key)

        ' AES decrypting
        aes.DecryptFile(New FileInfo("Data\EncryptedFile.aes"), New FileInfo("Data\Output.txt"), key)
        aes.DecryptFile(New FileInfo("Data\EncryptedWithIV.aes"), New FileInfo("Data\Output.txt"), key)
        aes.DecryptFile(New FileInfo("Data\EncryptedWithPassword.aes"), New FileInfo("Data\Output.txt"), key)
        aes.DecryptFile(New FileInfo("Data\EncryptedWithPasswordAndIV.aes"), New FileInfo("Data\Output.txt"), key)
    End Sub
End Class

Back to Top

AES Encrypting and decrypting a Stream

The Stream encryption is performed by reading the data from a Stream opened for reading and writing the encrypted output to a Stream that accepts write operations. After the method execution, the output Stream Position will be at the end of the encrypted data.

C# code

using System;
using System.IO;
using NCiphers.Ciphers;

class AES_Demo
{
    public static void Main(string[] args)
    {
        AES aes = new AES();
        // 16 bytes long key for AES-128 bit encryption
        byte[] key = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230};
        // optional 16 bytes long initialization vector
        byte[] IV = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106};

        using (Stream dataStream = File.OpenRead(@"Data\SampleFile.txt"))
        using (Stream encryptedStream = File.Create(@"Data\SampleFile.aes"))
        {
          aes.EncryptStream(dataStream, encryptedStream, key, IV);
        }

        Stream decryptedStream = new MemoryStream();
        using (Stream encryptedStream = File.OpenRead(@"Data\SampleFile.aes"))
        {
          aes.DecryptStream(encryptedStream, decryptedStream, key, IV);
        }
        // the output stream Position must be reset in order to read the decrypted data afterwards
        decryptedStream.Position = 0;
    }
}

VB.NET code

Imports System
Imports System.IO
Imports NCiphers.Ciphers

Class AES_Demo
    Public Shared Sub Execute()
        Dim aes As New AES()

        ' 16 bytes long key for AES-128 bit encryption
        Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230}
        ' optional 16 bytes long initialization vector
        Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106}

        Using dataStream As Stream = File.OpenRead("Data\SampleFile.txt")
            Using encryptedStream As Stream = File.Create("Data\SampleFile.aes")
                aes.EncryptStream(dataStream, encryptedStream, key, IV)
            End Using
        End Using

        Dim decryptedStream As New MemoryStream()
        Using encryptedStream As Stream = File.OpenRead("Data\SampleFile.aes")
            Using
                aes.DecryptStream(encryptedStream, decryptedStream, key, IV)
            End Using
        End Using
        ' the output stream Position must be reset in order to read the decrypted data afterwards
        decryptedStream.Position = 0
    End Sub
End Class

Back to Top

Encrypting and Decrypting a Byte array

The EncryptBytes and DecryptBytes methods accept byte array as input and return the output as byte array. The example below demonstrates the four possibilities for AES key and initialization vector (IV) offered by the library:

C# example

using System;
using System.IO;
using NCiphers.Ciphers;

class AES_Demo
{
    public static void Main(string[] args)
    {
        AES aes = new AES();
        // 16 bytes long key for AES-128 bit encryption
        byte[] key = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230};
        // optional 16 bytes long initialization vector
        byte[] IV = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106};

        byte[] data = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106};

        byte[] encryptedBytes = aes.EncryptBytes(data, key);
        byte[] encryptedBytesWithIV = aes.EncryptBytes(data, key, IV);
        byte[] encryptedBytesWithPassword = aes.EncryptBytes(data, "my password");
        byte[] encryptedBytesWithPasswordAndIV = aes.EncryptBytes(data, "my password", IV);

        byte[] decryptedBytes = aes.DecryptBytes(encryptedBytes, key);
        decryptedBytes = aes.DecryptBytes(encryptedBytesWithIV, key, IV);
        decryptedBytes = aes.DecryptBytes(encryptedBytesWithPassword, "my password");
        decryptedBytes = aes.DecryptBytes(encryptedBytesWithPasswordAndIV, "my password", IV);
    }
}

VB.NET example

Imports System
Imports System.IO
Imports NCiphers.Ciphers

Class AES_Demo
	Public Shared Sub Main(args As String())
		Dim aes As New AES()
		' 16 bytes long key for AES-128 bit encryption
		Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230}
		' optional 16 bytes long initialization vector
		Dim IV As Byte() = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106}

		Dim data As Byte() = {150, 9, 112, 39, 32, 5, 136, 289, 251, 43, 44, 191, 217, 236, 3, 106}

		Dim encryptedBytes As Byte() = aes.EncryptBytes(data, key)
		Dim encryptedBytesWithIV As Byte() = aes.EncryptBytes(data, key, IV)
		Dim encryptedBytesWithPassword As Byte() = aes.EncryptBytes(data, "my password")
		Dim encryptedBytesWithPasswordAndIV As Byte() = aes.EncryptBytes(data, "my password", IV)

		Dim decryptedBytes As Byte() = aes.DecryptBytes(encryptedBytes, key)
		decryptedBytes = aes.DecryptBytes(encryptedBytesWithIV, key, IV)
		decryptedBytes = aes.DecryptBytes(encryptedBytesWithPassword, "my password")
		decryptedBytes = aes.DecryptBytes(encryptedBytesWithPasswordAndIV, "my password", IV)
	End Sub
End Class

Back to Top

Exception handling

During the AES encryption and decryption operations errors can appear. In order to handle them more gracefully, the library offers a set of typed exceptions that can help us identify the cause of the error.

Below is an example class that demonstrates the various exceptions that can be expected during encryption and decryption. The methods that deal with files and streams of course may also throw System.IO.IOException sub classes:

C# code

using System;
using System.IO;
using NCiphers.Ciphers;

class AES_Exceptions
{
    public static void Main(string[] args)
    {
        AES aes = new AES();
        // 16 bytes long key for AES-128 bit encryption
        byte[] key = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230};

        try {
           aes.EncryptFile(new FileInfo(@"Data\SampleFile.txt"), new FileInfo(@"Data\EncryptedFile.aes"), key);
        } catch (System.ArgumentException) {
           Console.WriteLine("key size doesn't match algorithm or IV doesn't match the BlockSize");
        } catch (NCiphers.Exceptions.DataException) {
           if (aes.Padding.Equals(CipherPaddingMode.NoPadding)) {
            Console.WriteLine("input size not BlockSize aligned");
           } else {
            Console.WriteLine("this should never happen");
           }
        } catch (System.IO.IOException) {
           Console.WriteLine("I/O error");
        }

        try {
           aes.DecryptFile(new FileInfo(@"Data\EncryptedFile.aes"), new FileInfo(@"Data\Output.txt"), key);
        } catch (System.ArgumentException) {
           Console.WriteLine("key size doesn't match algorithm or IV doesn't match the BlockSize");
        } catch (NCiphers.Exceptions.CipherException) {
           Console.WriteLine("wrong key or password was supplied for decryption");
           Console.WriteLine("or different CipherBlockMode (property AES.Mode) was used for encryption");
        } catch (NCiphers.Exceptions.DataException) {
           Console.WriteLine("encrypted input is corrupted");
        } catch (System.IO.IOException) {
           Console.WriteLine("I/O error");
        }
    }
}

VB.NET code

Imports System
Imports System.IO
Imports NCiphers.Ciphers

Class AES_Exceptions
 Public Shared Sub Main(args As String())
	Dim aes As New AES()
	' 16 bytes long key for AES-128 bit encryption
	Dim key As Byte() = {50, 199, 10, 159, 132, 55, 236, 189, 51, 243, 244, 91, 17, 136, 39, 230}

	Try
		aes.EncryptFile(New FileInfo("Data\SampleFile.txt"), New FileInfo("Data\EncryptedFile.aes"), key)
	Catch generatedExceptionName As System.ArgumentException
		Console.WriteLine("key size doesn't match algorithm or IV doesn't match the BlockSize")
	Catch generatedExceptionName As NCiphers.Exceptions.DataException
		If aes.Padding.Equals(CipherPaddingMode.NoPadding) Then
			Console.WriteLine("input size not BlockSize aligned")
		Else
			Console.WriteLine("this should never happen")
		End If
	Catch generatedExceptionName As System.IO.IOException
		Console.WriteLine("I/O error")
	End Try

	Try
		aes.DecryptFile(New FileInfo("Data\EncryptedFile.aes"), New FileInfo("Data\Output.txt"), key)
	Catch generatedExceptionName As System.ArgumentException
		Console.WriteLine("key size doesn't match algorithm or IV doesn't match the BlockSize")
	Catch generatedExceptionName As NCiphers.Exceptions.CipherException
		Console.WriteLine("wrong key or password was supplied for decryption")
		Console.WriteLine("or different CipherBlockMode (property AES.Mode) was used for encryption")
	Catch generatedExceptionName As NCiphers.Exceptions.DataException
		Console.WriteLine("encrypted input is corrupted")
	Catch generatedExceptionName As System.IO.IOException
		Console.WriteLine("I/O error")
	End Try
 End Sub
End Class

Back to Top

Summary

This chapter illustrated how to perform AES encryption and decryption with the help of NCiphers.Crypto library.