Tuesday, December 10, 2013

C# Encryption Decryption Class AES

Sometimes you may need to use encryption and decryption class in your C# project. Here is a simple class you can use for above purpose feel free to use it and feedback with improvement. This class use Advance Encryption Standers. and RijndaelManaged method.





/*******************************************************************
File:         Crypter.cs
Author:       Nayana Adassuriya
Description:  Uses to encrypt or decrypt any string by symettric way (AES,RijndaelManaged) 
Language:     C#
Limitations:  Encription key genaration hashes are hardcoded in the class. 
              If some one knows these hashes, they can crate programe to decript the encripted strings. 
Thread Safe:  no  
Extendable:   yes 
Platform Depend:   Windows,.NET 3.5
Project:           None
*******************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace StorageService
{
  internal class Crypter
  {
    //Data members
    private static byte[] m_salt = Encoding.ASCII.GetBytes("41fb5b5ae4d57c5ee528adb00e5e8e74");
    private static string m_encrypt_key = "200911381f7899d2482ab61fe8d15684469b17fc690";


    /************************************************************************
    Purpose :         This is the method uses to encrypt plan strings.
    Parameters :      plan_test: text that need to be encrypted
    Returns :         encrypted string
    Exception :       If any exception while getting values from xml, pass to the upper level
    Algorithm :       C# manage code
    Output :          None
    Notes :           User can encrypt multiple times recursively if more security needs. If that
                      need to decrypt same number of rounds accordingly
    *************************************************************************/
    internal static string aesEncrypt(string plan_test)
    {
      string output = null;
      RijndaelManaged aes_alg = null;
      try
      {
        Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(m_encrypt_key, m_salt);
        aes_alg = new RijndaelManaged();
        aes_alg.Key = key.GetBytes(aes_alg.KeySize / 8);
        ICryptoTransform encryptor = aes_alg.CreateEncryptor(aes_alg.Key, aes_alg.IV);

        using (MemoryStream encrypt_ms = new MemoryStream())
        {
          encrypt_ms.Write(BitConverter.GetBytes(aes_alg.IV.Length), 0, sizeof(int));
          encrypt_ms.Write(aes_alg.IV, 0, aes_alg.IV.Length);
          using (CryptoStream encrypt_cs = new CryptoStream(encrypt_ms, encryptor, CryptoStreamMode.Write))
          {
            using (StreamWriter encrypt_sw = new StreamWriter(encrypt_cs))
            {
              encrypt_sw.Write(plan_test);
            }
          }
          output = Convert.ToBase64String(encrypt_ms.ToArray());
        }
      }
      catch (Exception e)
      {
        throw e;
      }
      finally
      {
        if (aes_alg != null)
        {
          aes_alg.Clear();
        }
      }
      return output;
    }

    /************************************************************************
    Purpose :         This is the method uses to decrypt the encrypted strings.
    Parameters :      cipher_text: decrypted string need to decrypt to plan text
    Returns :         Plan text after decrypted
    Exception :       If any exception while getting values from xml, pass to the upper level
    Algorithm :       C# manage code
    Output :          None
    Notes :           User can encrypt multiple times recursively if more security needs. If
                      that need to decrypt same number of rounds accordingly.
    *************************************************************************/
    internal static string aesDecrypt(string cipher_text)
    {
      RijndaelManaged aes_alg = null;
      string plain_text = null;
      try
      {
        Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(m_encrypt_key, m_salt);
        byte[] bytes = Convert.FromBase64String(cipher_text);
        using (MemoryStream decrypt_ms = new MemoryStream(bytes))
        {
          aes_alg = new RijndaelManaged();
          aes_alg.Key = key.GetBytes(aes_alg.KeySize / 8);
          aes_alg.IV = ReadByteArray(decrypt_ms);

          ICryptoTransform decryptor = aes_alg.CreateDecryptor(aes_alg.Key, aes_alg.IV);
          using (CryptoStream decrypt_cs = new CryptoStream(decrypt_ms, decryptor, CryptoStreamMode.Read))
          {
            using (StreamReader decrypt_sr = new StreamReader(decrypt_cs))
              plain_text = decrypt_sr.ReadToEnd();
          }
        }
      }
      catch (Exception e)
      {
        throw e;
      }
      finally
      {
        if (aes_alg != null)
          aes_alg.Clear();
      }
      return plain_text;
    }

    /************************************************************************
    Purpose :         Use to read first few bytes from cipher string( this helps to generate
                      the same key used in encrypt method again) 
    Parameters :      stream: stream that use to read the cipher text bytes from memory.
    Returns :         return byte array filled with first few bytes of the cipher string.
    Exception :       If any exception while getting values from xml, pass to the upper level
    Algorithm :       C# manage code
    Output :          None
    Notes :           None
    *************************************************************************/
    private static byte[] ReadByteArray(Stream stream)
    {
      byte[] buffer;
      byte[] row_length = new byte[sizeof(int)];
      try
      {
        if (stream.Read(row_length, 0, row_length.Length) != row_length.Length)
        {
          throw new SystemException("encrypted string not contain properly formatted byte array");
        }
        int temp = BitConverter.ToInt32(row_length, 0);
        buffer = new byte[temp];

        if (stream.Read(buffer, 0, buffer.Length) != buffer.Length)
        {
          throw new SystemException("Did not read encrypted string properly");
        }
      }
      catch (Exception e)
      {
        throw e;
      }
      return buffer;
    }
  }
}