miércoles, 21 de febrero de 2007

Encriptar cadenas en C#

Saludos internautas!
Ya tenía algún tiempo sin publicarme en este blog, pero de eso se habían encargado mi compadre MoYo y mi brother Kurt.
En esta ocasión les traigo una transcripción de un texto que puede servir de gran apoyo para aquellos que siguieron la entrada de Encriptación simple en VB. El texto, que MoYo fue quien me envió el enlace, lo saqué del sitio www.devjoker.com y su autor es Pedro Herrarte Sánchez.
Espero y les sirva a los recién iniciados en C#, un lenguaje bastante sencillo y poderoso. Si no... pregúntenle a mig16. :-P
Bueno... aquí tienen la transcripción:

Una clase sencilla para encriptar cadenas en C#


Uno de los problemas clásicos con los que nos enfrentamos los programadores es el de encriptar los datos. La cantidad de situaciones en las que necesitamos encriptar los datos es incontable.

Normalmente los datos se almacenan en una base de datos, y esta suele ser segura, pero las claves de conexión se encuentran en archivos de texto planos, XML ... Incluso hay muchas bases de datos en las que la información de las claves con las que los usuarios se conectan a los sistemas corporativos estan sin encriptar, con lo que además podemos llegar a comprometer la seguridad de todo nuestro sistema.

Existen complejos algoritmos que permiten la encriptación de datos y que garantizan matemáticamente que nadie los puede desencriptar, como es el caso de MD5, utilizado para emitir certificados de seguridad en sistemas SSL. Tambien existen componentes de software que realizan el trabajo de encriptación por nosotros.

Estas soluciones tienen su parte negativa, por un lado los algoritmos seguros no se pueden desencriptar, por lo que no siempre son utiles. Por otro lado los componentes de software desarrollados por compañias pueden llegar a ser muy caros y además es necesario instalarlos en el los servidores, cosa que no siempre es posible.

La solución son los sistemas de clave pública-privada. Son sistemas en los que la encriptación se basa en un par de claves, con una clave se encriptan los datos y sólo se pueden desencriptar si se conoce la otra.

Nuestra clase esta basada en esta idea. Vamos a desarrollar una clase que escripta cadena basandose en un patrones. La clase está escrita en VB.NET, pero al utilizar unicamente tipos comunes podemos exportarla facimente a cualquier otro lenguaje.

Lo primero que vamos a hacer es crear la clase a la que vamos a llamar Encriptador.

Public Class Encriptador

End Class


La idea de esta clase es definir dos patrones, cada uno con todos los caracteres del idioma, de la A-Z en mayúscula y minuscula, los numeros ... y cada uno en un orden diferente y aleatorio. Después aplicaremos un sencillo algoritmo que nos haga correcponder cada elemento de un patrón con otro.

Lo primero que necesitamos definir los patrones,para ello tecleamos el abecedario y los números en una cadena de texto como esta:

ABCDEFGHIJKLMNÑROPQRSTVWXYZabcdefghijklmnñropqrstvwxyz1234567890

Y ahora la desordenamos hasta que quede ilegible. Asignamos estas cadenas a nuestras cadena de patrón. Definimos las cadenas a nivel de instancia.

Tambien declaramos dos métodos, uno para encriptar la cadena y otro para encriptar una única letra, que además recibe otros dos parámetros, uno denominado variable, que representa la longitud de la cadena a encriptar y otro a_indice, que representa el índice del caracter dentro de la cadena. Con ellas construiremos un sencillo algoritmo, que evitará que alguien pueda establecer una relación del tipo de "la a es la j encriptada" y que hará que cada letra se encripte de modo diferente dependiendo de la longitud de la cadena y de donde esté situada dentro de ella.

Public Class Encriptador

Private patron_busqueda As String = "0ABIZ2ÑebDNOEcwGl6oSñixq1..."
Private
Patron_encripta As String = "vQÑO8dk1VgIPZxAR3UsLD6XBz..."
'Los patrones están aquí sin terminar por falta de espacio.


Public Function EncriptarCadena (ByVal cadena As String) As String

End Function

Private Function
EncriptarCaracter (ByVal caracter As String, ByVal variable As Integer, _
ByVal
a_indice As Integer) As String

End Function

End Class


Ahora escribimos el código para EncriptarCadena, que sencillamente recorre la cadena letra a letra invocando al método de encriptar caracter, pasandole como parémetros el caracter, la longitud de la cadena y el índice de la iteración. El código es muy sencillo.

Public Function EncriptarCadena (ByVal cadena As String) As String

Dim
idx As Integer
Dim
result As String
For
idx = 0 To cadena.Length - 1
result += EncriptarCaracter(cadena.Substring(idx, 1), cadena.Length, idx)

Next
Return
result

End Function


Ahora tenemos que escribir el método EncriptarCaracter, como hemos visto al declarar el método, recibe tres parámetros, el caracter que queremos encriptar, un entero variable (que será la longitud de la cadena a encriptar) y el indice que ocupa el caracter a encriptar dentro de la cadena que queremos encriptar. Esto nos va a permitir escribir un sencillo algoritmo para devolver el índice que le va a corresponder a nuestro caracter dentro del patron encriptado.

Private Function EncriptarCaracter (ByVal caracter As String, ByVal variable As Integer, _
ByVal
a_indice As Integer) As String
Dim
caracterEncriptado As String, indice As Integer

If patron_busqueda.IndexOf(caracter) <> -1 Then
indice = (patron_busqueda.IndexOf(caracter) + variable + a_indice)
Mod patron_busqueda.Length
Return Patron_encripta.Substring(indice, 1)
End If

Return caracter

End Function


La función busca el índice de mi caracter en la cadena denominada patron_busqueda, si lo encontramos (recordar que tenemos todas las letras y números), lo encriptamos, si no lo encontramos devolvemos el mismo caracter que hemos recibido como parámetro.

La encriptación en muy sencilla, ¡pero muy efectiva!, encontramos el lugar que ocupa dentro del patron de busqueda el caracter, le sumamos la longitud de la cadena y le sumamos por último el lugar que ocupa el caracter que estamos encriptando dentro de ella. Obtenemos el caracter correspondiente al índice calculado dentro del patron_encriptado. De este modo conseguimos que el mismo caracter se encripte de forma diferente en cada cadena, y que una pequeña modificación en la cadena cambie totalmente la encriptación.

Este algoritmo plantea un problema, ¿que ocurre cuando la suma de estos tres parámetro es superior a la longitud de los patrones?. Estariamos intentando estraer un elemento que supera los límites de las cadenas patrón. Para solucionar este problema trabajamos con módulos matemáticos. La operación módulo devuelve el resto de la división entera entre dos números. De este modo cuando nuestro índice supera los limites de la cadena, volvemos a la posición inicial.

Ejemplos con operaciones de modulos

15 Mod 20 ==> devuelve 15;

20
Mod 20 ==> devuelve 0

21
Mod 20 ==> devuelve 1

45
Mod 20 ==> devuelve 5


Ya tenemos nuestra clase que encripta cadenas, vamos a escribir una pequeña aplicación de consola que pruebe nuestra clase.

Module Encriptador_Test

Sub Main()

Dim cadena As String
Dim
enc As Encriptador
enc =
New Encriptador()
Do
Console.WriteLine("Introducca la cadena que quiera encriptar:")
cadena = Console.ReadLine()
Console.WriteLine( " ==> " + enc.EncriptarCadena(cadena))
Loop While cadena <> ""

End Sub

End Module


Vamos a ejecutar nuestro programa, y probamos a encriptar varias cadenas.

C:\VB.net\Encriptar\Encriptar\bin>encriptar.exe

Introducca la cadena que quiera encriptar:
Hola mundo! ==> 9QPz hpKIZ!

Introducca la cadena que quiera encriptar:
www.Devjoker.com ==> feo.Frfxy¥hb.jii

Introducca la cadena que quiera encriptar:
La misma letra varia aaaaaaaa! ==> YB WMb¤I JC¥yH Q¥CgP v7Ky8qj4!


Ahora necesitamos escribir lo métodos para desencriptar. Las declaraciones son parecidas.

Public Function DesEncriptarCadena(ByVal cadena As String) As String

End Function

Private Function
DesEncriptarCaracter(ByVal caracter As String, ByVal variable As Integer, _
ByVal
a_indice As Integer) As String

End Function


La implementación de los métodos tambien es sencilla, si bien el método de desencriptar caracter es algo más complicado, debido a la posibilidad de encontrar índices negativos. Aún así resultan faciles de comprender.

Public Function DesEncriptarCadena(ByVal cadena As String) As String

Dim
idx As Integer
Dim
result As String

For
idx = 0 To cadena.Length - 1
result+=DesEncriptarCaracter(cadena.Substring(idx, 1),cadena.Length,idx)

Next
return
result
End Function


Private Function
DesEncriptarCaracter(ByVal caracter As String, _
ByVal
variable As Integer, _
ByVal
a_indice As Integer) As String

Dim
indice As Integer

If Patron_encripta.IndexOf(caracter) <> -1 Then
If (Patron_encripta.IndexOf(caracter) - variable - a_indice) > 0 Then
indice = (Patron_encripta.IndexOf(caracter) - variable - a_indice)
Mod Patron_encripta.Length
Else
'La línea está cortada por falta de espacio
indice = (patron_busqueda.Length) + ((Patron_encripta.IndexOf(caracter)
- variable - a_indice)
Mod Patron_encripta.Length)
End If
indice = indice
Mod Patron_encripta.Length
Return patron_busqueda.Substring(indice, 1)
Else
Return
caracter
End If

End Function


Con esto ya tenemos escrito todo el código necesario. Como vereis no se trata de un sistema excesivamente seguro, pero para poder desencriptar nuestras cadenas es necesario conocer dos patrones de 64 caracteres, que además han sido generadas de forma aleatoria. Además este código es facilmente portable a cualquier plataforma, dado que se basa completamente en tipos sencillos, cadenas de caracteres, por lo que reescribir el codigo para una clase Java es muy facil.

El código necesario para que nuestra aplicación de consola desencripte es trivial, por lo que no lo comentaremos.

Bueno, espero que os haya parecido interesante el articulo, saludos y hasta la proxima.


Fuente: www.devjoker.com

No se olviden de visitar nuestro sitio!! Que ya fue lanzado en su primera versión BETA. www.shadowsecurity.8888mb.com (en un servidor temporal).

Saludos!

No hay comentarios.:

 

Visitante número:
ContactosPensionesTiendasCampingPracticas