Encriptación con .NET.

Encriptar un documento es la acción de convertir su contenido a un tipo de dato visual, físico o lógico, que no pueda ser entendible por el sujeto sin previamente haber convertido el sistema a un código entendible. Dicho de otra manera aplicamos la criptografía a los sistemas que queremos proteger para evitar un robo de la información.

El primer sistema criptográfico que se conoce fue la escítala, la cual era una serie de caracteres en una cinta de cuero que se enrrollaban sobre un palo de cierto diámetro y grosor que, el receptor del mensaje, debía de saber.

Escítala era el primer sistema de criptografía conocido

Esa era el primer sistema para cifrar la información de un mensaje, pero no era el único ya que en la era romana, salió el cifrado César, que desplazaba un número de caracteres del alfabeto hacia la izquierda o la derecha para hacer ininteligible un mensaje.

El cifrado CESAR tuvo mucho existo durante ciertos años y fue usado en la antigua Roma

Por desgracia estos sistemas dejaban mucho que desear porque los caracteres del mensaje no se cifraban, sino que simplemente cambiaban su posición mediante una clave asignada previa codificación y eran faciles de interpretar. Pero a partir del siglo XV, alguien se dió cuenta que era mejor que en lugar de cifrar un número de veces el texto era mejor pasar una clave al receptor y de ahí, que aplicara dicha clave para descifrar el mensaje. Nacieron así la criptografía polialfabética.

El cifrado Vigenère se basa en sumar, según los caracteres de una llave (clave), a las posiciones del mensaje. De tal forma que si tengo un texto "Este es un mensaje cifrado" y le paso la llave "desbloqueo", el mensaje que me devolverá será "ixmg qh li rtrxtlq rzawpht". Esto se debe a que la primera letra del mensaje a codificar (e) está en la posición 5 del alfabeto latino, mientras que la llave, la primera letra (d), está en la posición 4 del alfabeto. De esa forma si sumo ambos números me devuelve un número 7 que representa a la letra (i) del alfabeto latino. Con el resto de caracteres se procede de igual forma.

Otros tipos de cifrado mejorados y superiores como la famosa caja Enigma, ya hacian muy dificil la interpretación del mensaje. Por desgracia, en los tipos de cifradores de clave privada se necesitaba que el receptor tuviese la clave para poder interpretar el mensaje, lo que ocasionaba un problema de seguridad si un tercero capturaba la clave.

Y a partir de este problema surgieron otros sistemas de encriptación en donde la clave se transmitiría al receptor junto al mensaje cifrado en forma de clave pública como el sistema RSA, el sistema AES, etc., en los que se supone que el emisor y receptor del mensaje disponen de un par de claves. Una de cada par de claves, es pública y la conocerá todo el mundo, mientras que la otra clave es privada y solo la conocerá el receptor y emisor del mensaje cifrado.

El cifrado RSA es un cifrado asimétrico de par de claves

Y como ya está bien de historia, vamos a crear nuestros propios programas de cifrados basándonos en estos métodos criptográficos y gracias a la librería System.Security integrada en .NET.

Cifrado CÉSAR en VB.NET.

El cifrado CÉSAR se basa en el desplazamiento de los caracteres alfabeticos de un texto a cifrar, por lo que principalmente necesitaremos una variable que acumule cada carácter del alfabeto en cuestión. Pero antes creemos la estructura del programa.

Crea un nuevo proyecto de aplicación de escritorio, con el nombre del Codificador o el nombre que tu quieras ponerle. Y una vez abierto el formulario va a tener los siguientes controles:

● 3 TextBox.
● 2 Button.
● 3 Label.

Dos de los controles TextBox, deberán de ser Multilinea y los redimensionas como ves en la imagen. El nombre de los controles no es importante salvo el uso que le vas a dar si es para mostrar el texto o para escribir el texto. Las etiquetas Label son para diferenciar el campo de entrada y salida así como el rango de codificación. Los botones para cifrar y descrifar llamarán a dos funciones específicas (Cifrar(), y Descifrar())

Formulario del encriptador básico de César.

Como este cifrado recorre un número de posiciones de acuerdo a un array de caracteres, hay que establecer precisamente, dicho array. Para ello, usaremos un array de tipo char que contendrá los 27 caracteres de mi alfabeto (latino en mi caso). Además necesitaré una variable que se ocupe de guardar la posición que tiene cada carácter en dicho array. Por eso las dos primeras variables que creare en la aplicación serán públicas.

Variables públicas que permitirán manipular caracteres del mensaje

Función Cifrar.
Esta función se hará cargo de cifrar el contenido del mensaje escrito en el TextBox de la izquierda (en mi caso será TextBox1, es decir el nombre por defecto de VS.NET). Y además tenemos que establecer un rango, que es el número de caracteres que se desplazará en la codificación el texto original (en mi caso el TextBox3). El código de la función es el siguiente:


 Public Function cifrar(ByVal text As String) As String
        value = Integer.Parse(TextBox3.Text)
        Dim text1 As Char() = text.ToString()
        Dim cifrado As String() = New String(text.Length - 1) {}
        For i As Integer = 0 To text1.Length - 1
            For j As Integer = 0 To letras.Length - 1

                If String.Equals(text1(i), letras(j)) Then
                    If j = 26 Then
                        cifrado(i) = letras(-1 + value).ToString()
                    Else
                        If (j + value) > 26 Then
                            Dim aux As Integer = j + value - 27
                            cifrado(i) = letras(aux).ToString()
                        Else
                            cifrado(i) = letras(j + value).ToString()
                        End If
                    End If
                ElseIf String.Equals(" "c, text1(i)) Then
                    cifrado(i) = text1(i).ToString()
                End If
            Next
        Next
        Return String.Join("", cifrado)
    End Function
							

Vamos con la explicación. A la variable value, le asignamos el valor que introduzcamos en el TextBox3 de rango, por eso le aplicamos una función Parse e Integer, que convertirá el valor de dicho control a un tipo entero.

La variable text1 nos permitirá guardar los valores de cada carácter del array letras. La variable cifrado también juega un papel importante ya que según la estructura de los arrays, el elemento primero es el cero, de ahí que haya que recorrer todos los caracteres del texto de entrada menos el último (posiciona al puntero en el último carácter de la cadena).

Como tenemos que recorrer las letras del texto a cifrar y también los elementos del array letras, creamos dos bucles for anidados con el fin de que cada iteración de la cadena del TextBox1, se pueda relacionar con los items del array. Así el for i, recorre el texto del control TextBox1, mientras que el for j, recorre los elementos del array letras.

El primer condicional If compara los caracteres del texto introducido en el TexBox1 y el array letras. Si son iguales, se producirá una resta de los valores establecida mediante el valor del rango establecido por el TextBox3. Con esto hacemos que si los caracteres del texto a cifrar y el los items del array son el mismo, la codificación muestre otro carácter diferente al original.

Y si no son iguales, se producirá la suma del valor del TextBox3 teniendo en cuenta el valor introducido.

Punto de interrupción para comprobar el significado de cada valor

Es decir, el bucle for recorre cada letra del texto introducido y cada elemento del array e inserta el valor de cada iteración en la variable string de cifrado (tal como si hiciesemos una concatenación de letras). La función usa varios bucles y condicionales anidados de forma que según se vayan dando las condiciones, una nueva variable aux, vaya guardando el valor de las posiciones de los caracteres junto al valor del elemento. Todo con el fin de mostrar una salida diferente a la entrada.

Descifrar.
Para descifrar se usa la función descifrar que es muy parecido a la función cifrar. La única diferencia es en los condicionales que cambian el sentido y la igualdad de los elementos a establecer en los bucles for.


 Public Function Descifrar(ByVal text As String) As String
        value = Integer.Parse(textBox3.Text)
        Dim text1 As Char() = text.ToCharArray()
        Dim cifrado As String() = New String(text.Length - 1) {}
        For i As Integer = 0 To text1.Length - 1
            For j As Integer = 0 To letras.Length - 1
                If String.Equals(text1(i), letras(j)) Then
                    If j = 0 Then
                        cifrado(i) = letras(27 - value).ToString()
                    Else
                        If (j - value) < 0 Then
                            Dim aux As Integer = j - value + 27
                            cifrado(i) = letras(aux).ToString()
                        Else
                            cifrado(i) = letras(j - value).ToString()
                        End If
                    End If
                ElseIf String.Equals(" "c, text1(i)) Then
                    cifrado(i) = text1(i).ToString()
                End If
            Next
        Next
        Return String.Join("", cifrado)
    End Function
							

Como puedes ver cambian las líneas 8, 9, 11 y 12, que practicamente invierten el sentido de la función para conseguir el descifrado del texto.

Ahora con esto, si abres el programa y pones un texto y lo cifras, obtendrás un valor codificado al pulsar sobre el botón de Cifrar. Si pulsas sobre Descifrar, aparecerá el texto normal.

Cifrado AES en VB.NET.

Originalmente el cifrado AES en VB.NET viene de la clase abstracta de la cual deriva la anterior. Este encriptado simétrico conocido como Rijnael es un esquema de cifrado por bloques, estandarizado y muy usado en la actualidad.

el cifrado AES es un estándar de cifrado según la codificación por bloques

VB.NET también puede manejar esta estructura de bloques gracias a los algoritmos integrados en el espacio de nombres Cryptography de VS.NET, así que usaremos un objeto del recurso AesCryptoServiceProvider() para generar una codificación AES en nuestro programa. Para ello crearemos un nuevo Button que pondremos Cifrado AES como texto y dentro de él añadiremos la siguiente función:


Private Sub PROCESAR(ByVal PASSWORDTEXT As String, ByVal INTEXT As String,
ByVal OUTTEXT As String, ByVal ENCRIPTA As Boolean)
        Using INstream As New FileStream(INTEXT, FileMode.Open, FileAccess.Read)
            Using OUTstream As New FileStream(OUTTEXT, FileMode.Create,
FileAccess.Write)

                Dim MIAES As New AesCryptoServiceProvider()
                ' OBTIENE EL TAMAÑO VALIDO DE KEY
                Dim KEYSIZE As Integer = 0
                For i As Integer = 1024 To 1 Step -1
                    If MIAES.ValidKeySize(i) Then
                        KEYSIZE = i
                        Exit For
                    End If
                Next i
                Debug.Assert(KEYSIZE > 0)
                ' OBTIENE EL TAMAÑO VALIDO DE BLOCK
                Dim BLOCKSIZE As Integer = MIAES.BlockSize
                ' KEY , IV
                Dim KEY As Byte() = Nothing
                Dim IV As Byte() = Nothing

                Dim salt As Byte() = {&HA9, &HE3, &HF1, &H0, &HB5, &HA4, &HC5, &HD6,
&HD1, &HF3, &HFE, &H1F, &HDD, &HAA}
                Dim DERIVADOS As New Rfc2898DeriveBytes(PASSWORDTEXT, salt, 1000)
                KEY = DERIVADOS.GetBytes(KEYSIZE \ 8)
                IV = DERIVADOS.GetBytes(BLOCKSIZE \ 8)

                'ENCRIPTADOR/DESENCRIPTADOR.
                Dim ENCRIPTADOR As ICryptoTransform
                If ENCRIPTA = True Then
                    ENCRIPTADOR = MIAES.CreateEncryptor(KEY, IV)
                Else
                    ENCRIPTADOR = MIAES.CreateDecryptor(KEY, IV)
                End If
                Try
                    Using CRYPTOstream As New CryptoStream(OUTstream, ENCRIPTADOR,
CryptoStreamMode.Write)
                        Const BLOCK_SIZE As Integer = 1024
                        Dim BUFFER(BLOCK_SIZE) As Byte
                        Dim LEER As Integer
                        Do
                            LEER = INstream.Read(BUFFER, 0, BLOCK_SIZE)
                            If LEER = 0 Then Exit Do
                            CRYPTOstream.Write(BUFFER, 0, LEER)
                        Loop
                        CRYPTOstream.Flush()
                        CRYPTOstream.Close()
                    End Using
                Catch ex As Exception
                End Try
                ENCRIPTADOR.Dispose()
                INstream.Close()
                OUTstream.Close()
            End Using
        End Using
    End Sub
							

El anterior código parece extenso, pero no es nada más que otra función con 4 parámetros. Estos parámetros servirán para las variables que usaremos en nuestro programa para generar y guardar los textos en formato .txt. Con ello, más adelante en otras aplicaciones podremos enviar el texto codificado a un receptor con información sensible.

Sin importar lo que la función hace, la variable MIAES es una instancia de AesCryptoServiceProvider, que es el servicio que integra la función de codificación según la norma de cifrado AES. Además la función se encarga de guardar en texto plano el código sin codificar y en otro texto el código codificado, de tal manera que si quieres, puedes enviar el código codificado.

Puedes aprender más sobre el cifrado AES de Microsoft en el siguiente ENLACE.

Solo faltaría indicarle al receptor la clave para descifrar el mensaje, pero eso ya se va quedando fuera de esta práctica.

No olvides compartirlo, usarlo y mejorarlo. Así ayudarás a que mirpas sea más fuerte y pueda seguir ofreciendo contenido gratuito.

Y por supuesto el código fuente está disponible en mi GITHUB.