- Introduction to AES
- Padding and Block modes
- Encrypting and Decrypting a String
- Encrypting and Decrypting a File
- Encrypting and Decrypting a Stream
- Encrypting and Decrypting a Byte array
- Exception handling
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 |
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...
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
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
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
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
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
Summary
This chapter illustrated how to perform AES encryption and decryption with the help of NCiphers.Crypto library.