Saltar al contenido

Encriptar texto en C#

10 noviembre, 2020
Encriptar texto en c#

En ocasiones vamos a necesitar encriptar un texto en c# para usarlo con seguridad y posteriormente desencriptarlo, ya sea para una contraseña, una conexión a una base de datos, etc, así que en este artículo vamos a enseñar como hacerlo correctamente.

Hay diferentes maneras de encriptar un texto en c#, en este caso nosotros vamos a hacerlo bajo el estándar de cifrado avanzado de datos electrónicos conocido como AES. Establecido por el Instituto de Normas y Tecnología (NIST).

Qué es el cifrado AES?

La actualidad tecnológica nos brinda cada día nuevos y poderosos procesadores ultra-rápidos que pueden romper cada vez en menos tiempo un cifrado de texto.

La norma AES comenzó con un cifrado de 56bits pero en la actualidad tiene la posibilidad de cifrar a 128bits, 196bits o 256bits, donde cada vez es más seguro para nosotros.

Ventajas del sistema AES

Actualmente este tipo de cifrado ya se usa tanto en el ámbito público como en el privado, lo cuál tiene una gran ventaja frente a otros tipos de cifrado de texto.

Y otra ventaja que también hay que resaltar es que es un sistema de clave simétrico, es decir, que tanto para una encriptación o desencriptación de un texto, vas a necesitar una copia de llave correspondiente, por lo que al realizar una función u otra el usuario necesita conocer la clave perfectamente.

Dicho esto, y resumiendo, el sistema de cifrado AES es el sistema más seguro en la actualidad y su versión de 256 bits aún no ha sido capaz de romperla nadie.

Encriptar texto en C#

Dicho todo esto, vamos a explicar como se encripta un texto en c#.

Este sistema se basa en 4 métodos que la propia Microsoft nos brinda con su clase AES para que podemos hacerlo.

Una vez tengas creado tu proyecto necesitarás crear una clase, yo en mi caso la llamo Encryptacion.cs pero la puedes llamar como quieras.

En la página oficial de Microsoft la clase AES cambia sus métodos a medida que pasa el tiempo, por lo que mis métodos quizás no sea exactamente iguales.

Depende de cuando consultes este artículo variará en algo, pero a mi este método siempre me ha funcionado de maravilla, así que vamos a ello.

Una vez tengas abierto tu proyecto vas a necesitar 3 nuevas clases, una con los métodos de encriptación y otra clase para los métodos de desencriptación y una última clase para los métodos de guardado en archivos XML.

En mi ejemplo creo una nueva clase llamada encryptacion.cs y y comienzo con lo siguiente.

En la parte superior vas a necesitar un par de librerías para tratar los métodos de seguridad que son las siguientes:

using System.IO;
using System.Security.Cryptography;

Y más abajo vamos a necesitar 4 métodos que son los siguientes:

private byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            MemoryStream ms = new MemoryStream();
            Rijndael alg = Rijndael.Create();
            alg.Key = Key;
            alg.IV = IV;
            CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(clearData, 0, clearData.Length);
            cs.Close();
            byte[] encryptedData = ms.ToArray();
            return encryptedData;
        }
 public string Encrypt(string Data, string Password, int Bits)
        {
            byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(Data);
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x0, 0x1, 0x2, 0x1C, 0x1D, 0x1E, 0x3, 0x4, 0x5, 0xF, 0x20, 0x21, 0xAD, 0xAF, 0xA4 });
            if (Bits == 128)
            {
                byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(16), pdb.GetBytes(16));
                return Convert.ToBase64String(encryptedData);
            }
            else if (Bits == 192)
            {
                byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(24), pdb.GetBytes(16));
                return Convert.ToBase64String(encryptedData);
            }
            else if (Bits == 256)
            {
                byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
                return Convert.ToBase64String(encryptedData);
            }
            else
            {
                return String.Concat(Bits);
            }

        }
 private byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
       {
            MemoryStream ms = new MemoryStream();
            Rijndael alg = Rijndael.Create();
            alg.Key = Key;
            alg.IV = IV;
            CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
            cs.Write(cipherData, 0, cipherData.Length);
            cs.Close();
            byte[] decryptedData = ms.ToArray();
            return decryptedData;
        }
 public string Decrypt(string Data, string Password, int Bits)
        {
            try
            {
                byte[] cipherBytes = Convert.FromBase64String(Data);
                PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x0, 0x1, 0x2, 0x1C, 0x1D, 0x1E, 0x3, 0x4, 0x5, 0xF, 0x20, 0x21, 0xAD, 0xAF, 0xA4 });
                if (Bits == 128)
                {
                    byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(16), pdb.GetBytes(16));
                    return System.Text.Encoding.Unicode.GetString(decryptedData);
                }
                else if (Bits == 192)
                {
                    byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(24), pdb.GetBytes(16));
                    return System.Text.Encoding.Unicode.GetString(decryptedData);
                }
                else if (Bits == 256)
                {
                    byte[] decryptedData = Decrypt(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));
                    return System.Text.Encoding.Unicode.GetString(decryptedData);
                }
                else
                {
                    return String.Concat(Bits);
                }
            }
            catch (Exception ex)
            {
                return String.Concat(Bits);
            }
        }

No debemos tocar más esta clase, ahora necesitarás una nueva clase para desencriptar el texto, yo en mi caso la llamo desencryptar.cs, pero puedes llamarla como tu quieras.

Cómo desencriptar un texto en C#

Esta clase tendrá un par de métodos muy importantes ya que es aquí donde vamos a indicarle que texto vamos a usar como clave o contraseña única con la que va a desencriptar el texto en c#.

Explicándolo muy sencillamente, cogerá nuestro texto original, lo mezclará con nuestro texto clave única para poder desencriptarlo.

El texto lo vamos a ir guardando en un archivo XML, así que comenzamos por poner arriba la libreria necesaria:

using System.Xml;

A continuación los dos métodos de la clase:

class Desencryptacion
    {
        static private Encryptacion aes = new Encryptacion();
        static public string CnString;
        static string dbcnString;
        static public string appPwdUnique = "AquíPuedesPonerElTextoQueDeseesComoClaveUnica";


        public static object checkServer()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("ConnectionString.xml");
            XmlElement root = doc.DocumentElement;
            dbcnString = root.Attributes[0].Value;
            CnString = (aes.Decrypt(dbcnString, appPwdUnique, int.Parse("256")));
            return CnString;

        }
      
        public static object UsuariosEncryp()
        {
            XmlDocument doc = new XmlDocument();
            label root = new label();

            dbcnString = root.ToString();
            CnString = (aes.Decrypt(dbcnString, appPwdUnique, int.Parse("256")));
            return CnString;

        }
    }

Lo guardamos en un archivo XML

Es muy importante que te fijes que en el primer método llamadao checkServer() vamos a indicarle cuál es el archivo XML que vamos a comprobar, en mi caso lo llamaré ConnectionString.xml.

Este archivo debes crearlo dentro de tu proyecto en la ubicación c:/Usuarios/PEPE/source/repos/NombreDelProyecto/bin/debug

Donde PEPE será tu usuario personal de windows y NombreDelProyecto será como hayas llamado a tu proyecto.

Dentro del archivo debe contener lo siguiente:

<?xml version="1.0">
<database DBcnString="Cualquier texto inicial">
</database>

Es importante que en la cadena introduzcas algún texto inicial, el que sea, para que no falle, una vez que encriptes la primera vez, ahí se guardará nuestro texto encriptado y que podrás consultar para las pruebas.

Ahora puedes crear una clase nueva para las funciones XML como son leer y escribir:

public void SavetoXML(Object dbcnString)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("ConnectionString.xml");
            XmlElement root = doc.DocumentElement;
            root.Attributes[0].Value = Convert.ToString(dbcnString);
            XmlTextWriter writer = new XmlTextWriter("ConnectionString.xml", null);
            writer.Formatting = Formatting.Indented;
            doc.Save(writer);
            writer.Close();
        }
        string dbcnString;
        public void ReadfromXML()
        {
        try
            {

                XmlDocument doc = new XmlDocument();
                doc.Load("ConnectionString.xml");
                XmlElement root = doc.DocumentElement;
                dbcnString = root.Attributes[0].Value;
                txtCnString.Text = (aes.Decrypt(dbcnString, Desencryptacion.appPwdUnique, int.Parse("256")));
            }
            catch (System.Security.Cryptography.CryptographicException ex)
            {

            }
        }

Debes asegurarte bien de escribir el nombre del archivo tal como lo tienes creado dentro de tu carpeta de tu proyecto, en mi caso lo tengo como ConnectionString.xml

La carga de esta clase la puedes llamar de la siguiente forma y diciendole que lo primero que haga sea leer:

private void NombreClase_Load(object sender, EventArgs e)
{
    ReadfromXML();
}

Probamos que funciona nuestro código

Para finalizar vamos a suponer y a modo de ejemplo sencillo, para comprobar que todo esto funciona, que tenemos un formulario con un textBox y un button, debemos escribir nuestro texto a encriptar y al darle al botón que lo haga.

Podemos hacerlo así:

private void button1_Click(object sender, EventArgs e)
        {
            SavetoXML(Encryptación.Encrypt(txtBox1.Text, Desencryptacion.appPwdUnique, int.Parse("256")));
        }

Esto básicamente lo que hace es llamar a la clase Encryptacion y ejecutar el método Encrypt() con los siguientes parámetros:

  • Texto a encriptar que es nuestro textBox, en mi caso y para el ejemplo lo he llamado txtBox1.
  • El siguiente parámetro la clave única que hemos creado al principio de nuestra clase, en mi caso la he llamado appPwdUnique.
  • Y para acabar le decimos que queremos una clave de 256 bits, para ello debemos parsearla, porque se la estamos indicando en tipo cadena.

Debéis recordar el ámbito de los objetos, si vuestro botón está en otro sitio debéis tenerlo en cuenta para llamar a la clase encriptación y es posible que tengas que instanciarla antes como por ejemplo de este modo:

Encryptación encryp = new Encryptacion();

private void button1_Click(object sender, EventArgs e)
        {
            SavetoXML(encryp.Encrypt(txtBox1.Text, Desencryptacion.appPwdUnique, int.Parse("256")));
        }

Y si no podéis acceder a la clase, recordar que esta debe ser publica como he puesto yo.

Para saber si funciona, ejecutar vuestro proyecto, y rellenar un texto el que queráis en vuestra caja de texto, y pulsar el botón. (aseguraos que el formulario es lo primero que carga el proyecto, sino no tendréis manera de hacer la prueba)

En vuestro archivo de texto se habrá creado una cadena cifrada y bien protegida que sólo con una clave única y que sólo vosotros conocéis se puede desencriptar.

Espero que os haya servido de ayuda y recordar que tenéis más artículos sobre c# y xamarin. Y si piensas en tu futuro deberías leer nuestro articulo de cuales son los lenguajes de programación mejor pagados de 2021.

Configuraciones