domingo, 2 de septiembre de 2012

Cifrando Archivos con Rijndael

Hola que tal a todos esta en mi primera entrada y me gustaría mostrarles una clase para cifrar nuestros textos, fotos, vídeos o cualquier fichero que nos permita obtener su arreglo de bytes en las aplicaciones que desarrollamos con .net para este caso C#. Vamos  a utilizar el algoritmo Advanced Encryption Standard (AES), también conocido como Rijndael (pronunciado "Rain Doll" en inglés). Es un esquema de cifrado por bloques, pero bueno!!! mostremos el código, si tenemos duda con la parte teórica del  algoritmo, lo podemos encontrar rápidamente en wikipedia XD.  vamos a ver el código. 

//Mis namespaces 

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

namespace Helper
{
    public  class CifrandoAES
    {
      //Este método me ayudara a crear un IV  de 16 bytes. Para hacer esto mas rápido, le podemos enviar una cadena y obtener un hash de esa logitud con MD5, tal vez sea una mala practica pero funciona perfectamente :D 
        public byte[] CrearIV(string Cadena)
        {
            byte[] valueReturn = null;
            try
            {
                var CadenaBytes = System.Text.Encoding.UTF8.GetBytes(Cadena);

                System.Security.Cryptography.MD5CryptoServiceProvider xMD5 =
                    new System.Security.Cryptography.MD5CryptoServiceProvider();
                valueReturn = xMD5.ComputeHash(CadenaBytes);

            }
            catch { }
            return valueReturn;
        }
//Como necesitamos un Key de 32  bytes, aplico la misma técnica que arriba, Ingreso cualquier cadena a este método y gracias al método de digestión MD5, podemos obtener una cadena de 16  bytes. Como aquí necesitamos que la cadena sea de 32 bytes, simplemente aplico otro hash al resultado anterior, haciendo que el key obtenido sea casi imposible de saber por otra persona :D 
        public byte[] CrearKey(string Cadena)
        {
            byte[] valueReturn = new byte[32];
            try
            {
                var CadenaParteABytes = System.Text.Encoding.UTF8.GetBytes(Cadena);
                System.Security.Cryptography.MD5CryptoServiceProvider xMD5 =
                    new System.Security.Cryptography.MD5CryptoServiceProvider();
                xMD5.ComputeHash(CadenaParteABytes).CopyTo(valueReturn, 0);
                xMD5.ComputeHash(valueReturn).CopyTo(valueReturn, 16);

            }
            catch { }
            return valueReturn;
        }
 //Método para cifrar, al cual le pasaremos el arreglo de bytes del archivo mismo, nuestro Key y el IV, una vez hecho esto nos regresara el arreglo ya cifrado.
        public byte[] Cifrar(byte[]  Imagen, byte[] Key, byte[] IV)
        {
            try
            {
                // Crear una instancia del algoritmo de Rijndael  
                Rijndael RijndaelAlg = Rijndael.Create();
                // Establecer un flujo en memoria para el cifrado  
                MemoryStream MS = new MemoryStream();
                // Crear un flujo de cifrado basado en el flujo de los datos  
                CryptoStream CS = new CryptoStream(MS,
                    RijndaelAlg.CreateEncryptor(Key, IV),
                     CryptoStreamMode.Write);
                // Obtener la representación en bytes de la información a cifrar  
                byte[] TextoEnBytes = Imagen;
                // Cifrar los datos enviándolos al flujo de cifrado  
                CS.Write(TextoEnBytes, 0, TextoEnBytes.Length);
                CS.FlushFinalBlock();
                // Obtener los datos datos cifrados como un arreglo de bytes 
                byte[] TextoCifradoEnBytes = MS.ToArray();
                MS.Close();
                CS.Close();
                return TextoCifradoEnBytes;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
        public byte [] Descifrar(byte []ImagenCifrada, byte[] Key, byte[] IV)
        {
            try
            {
                // Obtener la representación en bytes del texto cifrado  
                byte[] TextoCifradoEnBytes = ImagenCifrada;
                // Crear un arreglo de bytes para almacenar los datos descifrados  
                byte[] TextoDescifrado = new byte[TextoCifradoEnBytes.Length];
                // Crear una instancia del algoritmo de Rijndael  
                Rijndael RijndaelAlg = Rijndael.Create();
                // Crear un flujo en memoria con la representación de bytes de la información cifrada  
                MemoryStream MS = new MemoryStream(TextoCifradoEnBytes);
                // Crear un flujo de descifrado basado en el flujo de los datos  
                CryptoStream CS = new CryptoStream(MS,
                    RijndaelAlg.CreateDecryptor(Key, IV),
                    CryptoStreamMode.Read);
                // Obtener los datos descifrados obteniéndolos del flujo de descifrado  
                int ContadorBytesDesencriptados = CS.Read(TextoDescifrado, 0, TextoDescifrado.Length);
                // Cerrar los flujos utilizados  
                MS.Close();
                CS.Close();
                return TextoDescifrado;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }        
    }
}

Espero les sirva esta clase. Yo la utilice para cifrar algunas imágenes. hasta ahora me funciona perfecto!!!