The .Net framework provides us several classes to encrypt data throws the System.Security.Cryptography namespace, in fact there is two ways to encrypt data either by using classes those support symmetric algorithms to hash data or the others those use the asymmetric ones.
In this article, I will propose a method of how to encrypt data and store it using symmetric algorithms whose are, in fact, four integrated classes within the .Net framework, namely DES,RC2,Rijndael and TripleDES but I will perform the task using the two last ones as they are the mostly used in real time cases.
To begin create a new console application project and add a new class into your project and name it then implement it as follow:
using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace CS
{
public enum EncryptionProvider
{ RijindaelManaged, TripleDES, };
class FileToHandle
{
private byte[] _Key = null;
private byte[] _IVector = null;
/* The SymetricAlgorithm is an abestrac class from witch
* all the symetic algorithm classes are derived I mark
* it as private because I will not use it directly I will
* cast it implicitly */
private SymmetricAlgorithm oSymmetricAlgorithm;
private string _FileName = null;
protected bool WitchAlgorithmToUse;
/// <summary>
/// This is the key property
/// </summary>
public byte[] Key
{
get { return _Key; }
set { _Key = value; }
}
/// <summary>
/// This is the intitial vector property
/// </summary>
public byte[] IVector
{
get { return _IVector; }
set { _IVector = value; }
}
/// <summary>
/// This is file path within witch I will store the data
/// </summary>
public string FileName
{
get { return _FileName; }
set { _FileName = value; }
}
/*For this class I will add this constructor it is overloaded by both
* * the file name witch indicates the path of the stored data then
* the EncryptionProvider witch indicates witch of both classes will
* be used RijindaelManaged or TripleDES */
/// <summary>
/// The class constructor
/// </summary>
/// <param name="FileName">string: indicates the stored data file path</param>
/// <param name="oEncryptionProvider">enum:indicates witch algorithm to use</param>
public FileToHandle(string FileName, EncryptionProvider oEncryptionProvider)
{
this.FileName = FileName;
if (oEncryptionProvider == EncryptionProvider.RijindaelManaged)
{ WitchAlgorithmToUse = true; }
if (oEncryptionProvider == EncryptionProvider.TripleDES)
{ WitchAlgorithmToUse = false; }
}
/// <summary>
/// This method is used to generate the key and the initial vector
///whose are used to hash data I mark it protected as I dont want
///to expose it to the final user
/// </summary>
protected void Generate()
{
/* In this case WitchAlgorithmToUse is setted to false*/
if (!WitchAlgorithmToUse)
{
oSymmetricAlgorithm = new TripleDESCryptoServiceProvider();
oSymmetricAlgorithm.GenerateKey();
oSymmetricAlgorithm.GenerateIV();
Key = oSymmetricAlgorithm.Key;
IVector = oSymmetricAlgorithm.IV;
}
/* In this case WitchAlgorithmToUse is setted to true*/
if (WitchAlgorithmToUse)
{
oSymmetricAlgorithm = new RijndaelManaged();
Key = oSymmetricAlgorithm.IV;
IVector = oSymmetricAlgorithm.IV;
oSymmetricAlgorithm.GenerateKey();
oSymmetricAlgorithm.GenerateIV();
}
}
/// <summary>
/// This method encrypts the data
/// </summary>
/// <param name="inputData">string : data to encrypt</param>
public void Encrypt(string inputData)
{
//Encode data to bytes and put them in a bytes array
byte[] DataToEncrypt = Encoding.Unicode.GetBytes(inputData);
//Create a file stream to store data within it
using (FileStream oStream = new FileStream(FileName, FileMode.Create, FileAccess.Write))
{
//invoke the generate method to generate the key and the initial vector
Generate();
//create encryptor using oSymmetricAlgorithm.CreateEncryptor method
//The ICryptoTransform defines the basic operations of cryptographic transformations.
using (ICryptoTransform oTransform = oSymmetricAlgorithm.CreateEncryptor(Key, IVector))
{
//Define a stream that links data streams to cryptographic transformations by using CryptoStream class.
using (CryptoStream oCryptoStream = new CryptoStream(oStream, oTransform, CryptoStreamMode.Write))
{
try
{
oCryptoStream.Write(DataToEncrypt, 0, DataToEncrypt.Length);
Console.WriteLine("Encryption is done successfully");
}
//Catch exceptions that could happen
catch (IOException caught) { Console.WriteLine(caught.Message); }
catch (ArgumentNullException caught) { Console.WriteLine(caught.Message); }
catch (FormatException caught) { Console.WriteLine(caught.Message); }
}
}
}
}
/// <summary>
/// This method decrypts the data
/// </summary>
/// <param name="outputData">string : the decrypted data</param>
public void Decrypt(out string outputData)
{
Console.WriteLine("Begin decryption");
outputData = "";
//Create a file stream to read data from within it
using (FileStream oStream = new FileStream(FileName, FileMode.Open, FileAccess.Read))
{
//The binary reader will read data from stream as binary entity
using (BinaryReader oBinaryReader = new BinaryReader(oStream))
{
long Max = oBinaryReader.BaseStream.Length;
//Put the file content into an array of bytes
byte[] ContentToBytes = oBinaryReader.ReadBytes(Convert.ToInt32(Max));
//Encode the bytes to chars
char[] ContentToChar = Encoding.Unicode.GetChars(ContentToBytes);
//Transform the char array to string
string inputString = new string(ContentToChar);
//Set the current position of this stream
oStream.Seek(0, SeekOrigin.Begin);
using (ICryptoTransform oTransform = oSymmetricAlgorithm.CreateDecryptor(Key, IVector))
{
using (CryptoStream oCryptoStream = new CryptoStream(oStream, oTransform, CryptoStreamMode.Read))
{
//Read the data within the crypto stream using a stream reader instance
StreamReader oReader = new StreamReader(oCryptoStream, new UnicodeEncoding());
try
{
outputData = oReader.ReadToEnd();
}
//Catch exceptions that could happen
catch (OutOfMemoryException caught) { Console.WriteLine(caught.Message); }
catch (IOException caught) { Console.WriteLine(caught.Message); }
//Write the result into the console
Console.WriteLine("The decrypted data is : " + outputData);
Console.WriteLine("End of decryption");
}
}
}
}
}
}
}
To try encryption/decryption of data, use this code:
namespace CS
{
class Program
{
public static void Main(string[] args)
{
FileToHandle x = new FileToHandle(@"C:\Test.txt", EncryptionProvider.RijindaelManaged);
string data = "Bejaoui Bechir";
Console.WriteLine("This is the data to encrypt " + data);
x.Encrypt(data);
string result;
x.Decrypt(out result);
Console.Read();
Console.Beep();
}
}
}
The FileToHandle class displays a flexibility concerning the choice of witch algorithm to chose, it depends on the protected bool WitchAlgorithmToUse value whether it is true or false and the result will be Of Corse, an encrypted data located within "C:\Test.txt", as a result of Bejaoui Bechir's encryption.