miércoles, 3 de junio de 2015

Cifrado y descifrado simétrico con Rijndael (AES) utilizando C#/

Cascaron DataLayerIng Advanced Encryption Standard (AES), también conocido como Rijndael, es un algoritmo de cifrado por bloques que es parte del estándar de Estados Unidos y actualmente es uno de los algoritmos de cifrado mas populares de criptografia simétrica.

Este tipo de algoritmos se pueden usar tanto para cifrar cadenas como archivos empecemos por las cadenas:

Implementación sobre cadenas (Strings)


La Implementación de este Algoritmo requiere los namespaces:
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;

Clave y Vector de Inicio


Estos Valores son los que determinan la encripcion del algoritmo, estos valores pueden ser especificados manualmente o de manera automática por le mismo FrameWork La implementación queda definida por el siguiente código:

Rijndael rijndael = Rijndael.Create();
byte[] key = rijndael.Key;
byte[] iv  = rijndael.IV;

Es posible forzar la generación de nuevas claves y números de vectores de inicio para para el algoritmo utilizando los metodos rijndael.GenerateKey() y rijndael.GenerateIV() respectivamente.

Si el usuario o programador desea insertar los datos  para estos valores se usaran las variables strKey y strIv

byte[] key = UTF8Encoding.UTF8.GetBytes(strKey);
byte[] iv  = UTF8Encoding.UTF8.GetBytes(strIv);

Especificando estos valores manualmente es necesario garantizar que sus longitudes sean válidas para el algoritmo.  En este caso se utilizará una longitud de clave de 32 bits y una longitud de vector de inicio de 16 bits.

Array.Resize(ref key, keySize);
Array.Resize(ref iv, ivSize);

Cifrado de cadenas de texto.


Para cifrar la información se requiere de los siguientes parámetros.

  1. Cadena de texto con los datos a cifrar.
  2. Clave.
  3. Vector de inicio.

El proceso retornará finalmente una cadena de texto con los datos cifrados; para ello se implementa la siguiente funcion.
///
        /// 
        /// Cifrado de Cadenas de Texto
        /// 
        /// Mensaje a Cifrar
        /// Valor de la llave
        /// Vector de Inicio
        /// 
        public static string encryptString(String plainMessage, byte[] Key, byte[] IV)
        {
            Rijndael RijndaelAlg = Rijndael.Create();
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                         RijndaelAlg.CreateEncryptor(Key, IV),
                                                         CryptoStreamMode.Write);
            byte[] plainMessageBytes = UTF8Encoding.UTF8.GetBytes(plainMessage);
            cryptoStream.Write(plainMessageBytes, 0, plainMessageBytes.Length);
            cryptoStream.FlushFinalBlock();
            byte[] cipherMessageBytes = memoryStream.ToArray();
            memoryStream.Close();
            cryptoStream.Close();
            return Convert.ToBase64String(cipherMessageBytes);
        }

Descifrado de cadenas de texto.


El proceso inverso, el de descifrado, se realiza de manera antagónica.  Para hacerlo es necesario contar con los siguientes parámetros.

Cadena de texto con los datos cifrados.
Clave.
Vector de inicio.
El proceso retornará finalmente una cadena de texto con los datos descifrados.
///
        /// Descifrado de cadenas de texto
        /// 
        /// Mensaje Encriptado
        /// Valor de la llave
        /// Vector de Inicio
        /// 
        public static string decryptString(String encryptedMessage, byte[] Key, byte[] IV)
        {
            byte[] cipherTextBytes = Convert.FromBase64String(encryptedMessage);
            byte[] plainTextBytes = new byte[cipherTextBytes.Length];
            Rijndael RijndaelAlg = Rijndael.Create();
            MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
            CryptoStream cryptoStream = new CryptoStream(memoryStream,
                                                         RijndaelAlg.CreateDecryptor(Key, IV),
                                                         CryptoStreamMode.Read);
            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
            memoryStream.Close();
            cryptoStream.Close();
            return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
        }

Implementación con Archivos

El cifrado y descifrado de mensajes en archivos se realiza de manera similar al expuesto anteriormente con cadenas, sin embargo varían los flujos (streams) utilizados para obtener y dirigir el flujo de la información.

///

        /// Encriptar un Archivo
        /// 
        /// Mensajea Cifrar        
        /// Nombre del archivo
        /// Valor de la llave
        /// Vector de Inicio
        public static void encryptToFile(String plainMessage,String filename, byte[] Key, byte[] IV)
        {
            FileStream fileStream = File.Open(filename, FileMode.OpenOrCreate);
            Rijndael RijndaelAlg = Rijndael.Create();
            CryptoStream cryptoStream = new CryptoStream(fileStream,
                                                         RijndaelAlg.CreateEncryptor(Key, IV),
                                                         CryptoStreamMode.Write);
            StreamWriter streamWriter = new StreamWriter(cryptoStream);
            streamWriter.WriteLine(plainMessage);
            streamWriter.Close();
            cryptoStream.Close();
            fileStream.Close();
        }
        /// 
        /// 
        /// 
        /// Nombre del archivo cifrado
        /// Valor de la llave
        /// Vector de Inicio
        /// Mensaje Encriptado
        public static string decryptFromFile(String filename, byte[] Key, byte[] IV)
        {
            FileStream fileStream = File.Open(filename, FileMode.OpenOrCreate);
            Rijndael RijndaelAlg = Rijndael.Create();
            CryptoStream cryptoStream = new CryptoStream(fileStream,
                                                         RijndaelAlg.CreateDecryptor(Key, IV),
                                                         CryptoStreamMode.Read);
            StreamReader streamReader = new StreamReader(cryptoStream);
            string plainMessage = streamReader.ReadLine();
            
            streamReader.Close();
            cryptoStream.Close();
            fileStream.Close();

            return plainMessage;
        }

No hay comentarios:

Publicar un comentario