AES is a symmetric cipher. Some of you may be wondering, what does that mean? Well, a symetric cipher is one that typically uses one key for both encryption and decryption. Basically you need to "share" the key with the other party, which is why sometimes symmetric ciphers are called shared key ciphers. I would love to do a tutorial on public key cryptography or one comparing both symmetric and public key if this tutorial turns out good and people would want one.
Ok enough history and background, if you would like to learn more specifically about AES check this out Here.
For this (my first tutorial) I really think a basic start is appropriate.
What we are going to accomplish with this? I plan on writing here a simple program that takes in a message from a user to encrypt and decrypt then display that back. So lets get started.
First create a C# console app. Then we are going to need to include just three things.
using System; //System.IO we include for the access to the memory stream using System.IO; //The big using here, this includes everything you could want to do with cryptography. //Including hashing and public key or semetric key cryptography. //Gives us acess to cryptostream, the crypto transforms and the rijndael class. using System.Security.Cryptography;
Little explanation here, when the RijndaelManaged constructor is called it creates both the key and the Initialization Vector(IV). (For the purposes of this tutorial I am using the generated IV and Key.) The key is like a password built in when you encrypt, and checked when you decrypt. I am going to let wikipedia explain IV's "In cryptography, an initialization vector (IV) is a block of bits that is required to allow a stream cipher or a block cipher to be executed in any of several streaming modes of operation to produce a unique stream independent from other streams produced by the same encryption key, without having to go through a (usually lengthy) re-keying process." Basically it keeps track of your bits and allows you to use the same key for multiple encrypts and decrypts.
//This class here the Rijndael is what will have most all of the methods we need to do aes encryption. //When this is called it will create both a key and Initialization Vector to use. RijndaelManaged Crypto = new RijndaelManaged();
I will talk about things that are commented so forgive the repeats.
Let us go over the encrypt function, which returns a byte array holding the encrypted data.
The first thing to make sure is that you have both the original IV and Key. Use the RijndaelManaged.Key or RijndaelManaged.IV property to pass them around.
The big things to pay attention to are the BIG THREE the RijndaelManaged, ICryptoTransform and the CryptoStream.
The ICryptoTransform is used to encrypt and decrypt, it is created with either the encrypt method or decrypt method of the RijndaelManaged class, which take the key and IV as parameters.
// Just here so you can see RijndaelManaged Crypto = new RijndaelManaged(); ICryptoTransform Encryptor = Crypto.CreateEncryptor(Crypto.Key, Crypto.IV);
Next is the CryptoStream. The CryptoStream allows for encryption in memory and even inherits from MemoryStream. CryptoStream is passed three parameters a memory stream, the type of transformation and the Cryptographic mode to work through which can be Write ( for encryption) or read ( for decryption).
Crypto_Stream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
The last thing that really needs mentioning is the CryptoStream.Write method, where you will be actually writing to the stream. The method takes three parameters the first (and here is a big point) needs to be in bytes, in our case we need to convert the text to bytes in the function this is done by encoding and then calling the getbytes method. The next parameter is an offset unless you have a good reason leave this as zero, lastly I am using the encoded string to get its length which is passed to the stream. Really that is about it, the rest of the function is pretty self explanatory.
//The object that encodes and has getbytes as well as the length method
System.Text.UTF8Encoding Byte_Transform = new System.Text.UTF8Encoding();
Crypto_Stream.Write(PlainBytes, 0, PlainBytes.Length);
The Encrypt Function
private static byte[] encrypt_function(string Plain_Text, byte[] Key, byte[] IV)
{
RijndaelManaged Crypto = null;
MemoryStream MemStream = null;
//I crypto transform is used to perform the actual decryption vs encryption, hash function are also a version of crypto transform.
ICryptoTransform Encryptor = null;
//Crypto streams allow for encryption in memory.
CryptoStream Crypto_Stream = null;
System.Text.UTF8Encoding Byte_Transform = new System.Text.UTF8Encoding();
//Just grabbing the bytes since most crypto functions need bytes.
byte[] PlainBytes = Byte_Transform.GetBytes(Plain_Text);
try
{
Crypto = new RijndaelManaged();
Crypto.Key = Key;
Crypto.IV = IV;
MemStream = new MemoryStream();
//Calling the method create encryptor method Needs both the Key and IV these have to be from the original Rijndael call
//If these are changed nothing will work right.
Encryptor = Crypto.CreateEncryptor(Crypto.Key, Crypto.IV);
//The big parameter here is the cryptomode.write, you are writing the data to memory to perform the transformation
Crypto_Stream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
//The method write takes three params the data to be written (in bytes) the offset value (int) and the length of the stream (int)
Crypto_Stream.Write(PlainBytes, 0, PlainBytes.Length);
}
finally
{
//if the crypto blocks are not clear lets make sure the data is gone
if (Crypto != null)
Crypto.Clear();
//Close because of my need to close things when done.
Crypto_Stream.Close();
}
//Return the memory byte array
return MemStream.ToArray();
}
The decryption function is VERY similar to the encryption function, the major things that need pointing out are as follows.
Your ICryptoTransform will now be passed the decrypt method of the RijndaelManaged class.
Decryptor = Crypto.CreateDecryptor(Crypto.Key, Crypto.IV);
The CryptoStream will now be called with the Read method.
Crypto_Stream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read);
Lastly for this I used a stream reader. As is stated in the comments this just makes it so much easier to get the data from the stream. The ReadToEnd method and the fact that the stream reader returns a string makes life easy, so use it. The StreamReader only needs to be called with the Crypto_Stream inserted.
Stream_Read = new StreamReader(Crypto_Stream); //Store the text and return. Plain_Text = Stream_Read.ReadToEnd();
The decryption function.
private static string decrypt_function(byte[] Cipher_Text, byte[] Key, byte[] IV)
{
RijndaelManaged Crypto = null;
MemoryStream MemStream = null;
ICryptoTransform Decryptor = null;
CryptoStream Crypto_Stream = null;
StreamReader Stream_Read = null;
string Plain_Text;
try
{
Crypto = new RijndaelManaged();
Crypto.Key = Key;
Crypto.IV = IV;
MemStream = new MemoryStream(Cipher_Text);
//Create Decryptor make sure if you are decrypting that this is here and you did not copy paste encryptor.
Decryptor = Crypto.CreateDecryptor(Crypto.Key, Crypto.IV);
//This is different from the encryption look at the mode make sure you are reading from the stream.
Crypto_Stream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read);
//I used the stream reader here because the ReadToEnd method is easy and because it return a string, also easy.
Stream_Read = new StreamReader(Crypto_Stream);
Plain_Text = Stream_Read.ReadToEnd();
}
finally
{
if (Crypto != null)
Crypto.Clear();
MemStream.Flush();
MemStream.Close();
}
return Plain_Text;
}
That is really about it. Below is the full code for people who want to Copy and Paste. Thanks for the time. I really hope this tutorial proves useful and if it is please tell me I want to continue to write about using some of the things offered in the System.Security.Cryptography namespace. If it is not useful please tell me and I will try to correct the problems.

using System;
//System.IO we include for the access to the memory stream
using System.IO;
//The big using here, this includes everything you could want to do with cryptography.
//Including hashing and public key or semetric key cryptography.
//Gives us acess to cryptostream, the crypto transforms and the rijndael class.
using System.Security.Cryptography;
namespace AES_Tutuorial
{
class Crypto_tut
{
static void Main()
{
string Plain_Text;
string Decrypted;
string Encrypted_Text;
byte[] Encrypted_Bytes;
//This class here the Rijndael is what will have most all of the methods we need to do aes encryption.
//When this is called it will create both a key and Initialization Vector to use.
RijndaelManaged Crypto = new RijndaelManaged();
//This is just here to convert the Encrypted byte array to a string for viewing purposes.
System.Text.UTF8Encoding UTF = new System.Text.UTF8Encoding();
Console.WriteLine("Please put in the text to be encrypted.");
Plain_Text = Console.ReadLine();
try
{
Encrypted_Bytes = encrypt_function(Plain_Text, Crypto.Key, Crypto.IV);
Encrypted_Text = UTF.GetString(Encrypted_Bytes);
Decrypted = decrypt_function(Encrypted_Bytes, Crypto.Key, Crypto.IV);
Console.WriteLine("Start: {0}", Plain_Text);
Console.WriteLine("Encrypted: {0}", Encrypted_Text);
Console.WriteLine("Decrypted: {0}", Decrypted);
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.Message);
}
Console.WriteLine("Press enter to exit");
Console.ReadKey();
}
private static byte[] encrypt_function(string Plain_Text, byte[] Key, byte[] IV)
{
RijndaelManaged Crypto = null;
MemoryStream MemStream = null;
//I crypto transform is used to perform the actual decryption vs encryption, hash function are a version of crypto transforms.
ICryptoTransform Encryptor = null;
//Crypto streams allow for encryption in memory.
CryptoStream Crypto_Stream = null;
System.Text.UTF8Encoding Byte_Transform = new System.Text.UTF8Encoding();
//Just grabbing the bytes since most crypto functions need bytes.
byte[] PlainBytes = Byte_Transform.GetBytes(Plain_Text);
try
{
Crypto = new RijndaelManaged();
Crypto.Key = Key;
Crypto.IV = IV;
MemStream = new MemoryStream();
//Calling the method create encryptor method Needs both the Key and IV these have to be from the original Rijndael call
//If these are changed nothing will work right.
Encryptor = Crypto.CreateEncryptor(Crypto.Key, Crypto.IV);
//The big parameter here is the cryptomode.write, you are writing the data to memory to perform the transformation
Crypto_Stream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
//The method write takes three params the data to be written (in bytes) the offset value (int) and the length of the stream (int)
Crypto_Stream.Write(PlainBytes, 0, PlainBytes.Length);
}
finally
{
//if the crypto blocks are not clear lets make sure the data is gone
if (Crypto != null)
Crypto.Clear();
//Close because of my need to close things then done.
Crypto_Stream.Close();
}
//Return the memory byte array
return MemStream.ToArray();
}
private static string decrypt_function(byte[] Cipher_Text, byte[] Key, byte[] IV)
{
RijndaelManaged Crypto = null;
MemoryStream MemStream = null;
ICryptoTransform Decryptor = null;
CryptoStream Crypto_Stream = null;
StreamReader Stream_Read = null;
string Plain_Text;
try
{
Crypto = new RijndaelManaged();
Crypto.Key = Key;
Crypto.IV = IV;
MemStream = new MemoryStream(Cipher_Text);
//Create Decryptor make sure if you are decrypting that this is here and you did not copy paste encryptor.
Decryptor = Crypto.CreateDecryptor(Crypto.Key, Crypto.IV);
//This is different from the encryption look at the mode make sure you are reading from the stream.
Crypto_Stream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read);
//I used the stream reader here because the ReadToEnd method is easy and because it return a string, also easy.
Stream_Read = new StreamReader(Crypto_Stream);
Plain_Text = Stream_Read.ReadToEnd();
}
finally
{
if (Crypto != null)
Crypto.Clear();
MemStream.Flush();
MemStream.Close();
}
return Plain_Text;
}
}
}





MultiQuote






|