Encriptación Hash (Contraseñas)

Published Sun, Nov 28 2004 0:08

Éste es un algoritmo de los que se conocen como de sólo ida, ya que no es posible desencriptar lo que se ha encriptado. Puede ser que a primera vista no se le vea la utilidad, pero en los siguientes dos escenarios, éste es el algoritmo necesario para realizar el proceso. En éstos, el primero es proteger información muy valiosa encriptando el contenido y el segundo es validar que no se modifique la información que se está enviando desde algún lugar a otro. Veamos el primer escenario.

Almacenar contraseñas de un sistema. Las contraseñas de cualquier sistema serio jamás debieran poder desencriptarse. El motivo es simple. Si se pueden desencriptar, el riesgo que alguien conozca la llave y tenga acceso a todo el sistema con todos los usuarios es muy grande. Entonces, si no puedo desencriptar una contraseña, ¿Cómo puedo saber entonces si una contraseña entregada es válida si no puedo compararla? La respuesta es muy simple. Se encripta la contraseña entregada y se compara el resultado de la encriptación con la contraseña previamente almacenada.

Problemas: Si bien el problema no está tan relacionado con el Hash, debido a la utilización de contraseñas de escasa dificultad, haciendo un ataque de fuerza bruta o por diccionario se podrían encontrar valores de Hash que coinciden con el Hash de las contraseñas almacenadas. Para esto se pueden ejecutar dos planes de acción independientes, pero obteniéndose el mejor resultado con la utilización de ambos.

La solución 1 consiste en realizar varias pasadas de Hash sobre los datos, aplicándole el Hash al resultado del Hash anterior. Realizando esto varios cientos de veces (idealmente mil veces) podemos dificultar más el trabajo de un hacker.

La solución 2 requiere agregar un texto adicional a la contraseña. Esto se conoce como Salt. Entonces, cada vez que un usuario cambie o esté validando una contraseña, hay que concatenarle a la contraseña este Salt y de ahí generar el Hash. De esta forma le agrega variación a las contraseñas pobremente definidas. Esta solución requiere un trabajo adicional ya que es necesario además almacenar el texto del Salt junto a la información del usuario y la contraseña encriptada. Este texto se debe crear con caracteres generados al azar.

En el ejemplo se mostrará la combinación de ambas soluciones. Como encriptación de Hash se usará SHA1. Los otros algoritmos mencionados con anterioridad están disponibles también en .NET.

public static byte[] Encriptar(string strPassword, string strSalt, int intIteraciones)

{

      string _strPasswordSalt = strPassword + strSalt;

      SHA1 _objSha1 = SHA1.Create();

      byte[] _objTemporal = null;

      try

      {

              _objTemporal = System.Text.Encoding.UTF8.GetBytes(_strPasswordSalt);

              for (int i = 0; i <= intIteraciones-1; i++)

                     _objTemporal = _objSha1.ComputeHash(_objTemporal);

       }

       finally

       {

              _objSha1.Clear();

       }

       return _objTemporal;

}

El resultado de este Hash (Sha1) siempre retorna 160 bits, es decir, 20 bytes. Cuidado con confundir con el largo del string resultante de la conversión a Base64. Esta conversión genera más caracteres. Para verificar, pueden medir el largo del arreglo colocando un punto de interrupción en el retorno (return), y notarán que son 20 bytes.

Además, las funciones de hash no tienen limitante para el tamaño del texto de entrada. Sea cual sea el tamaño, el largo de la salida es el mismo y se procesan todos los caracteres del string de entrada.

Para un sistema de almacenamiento de contraseñas de usuario seguro, hay que hacer algunas modificaciones a esta función, pero son mínimas. Las modificaciones no pasan por cambios en el algoritmo, sino mas bien por crear una función para que genere Salt randómicos y crear la función para la comparación de las contraseñas.

La función para comparar arreglos de Bytes es la siguiente

private static bool CompareByteArray(Byte[] arrayA, Byte[] arrayB)

{

       if (arrayA.Length != arrayB.Length) return false;

       for (int i = 0 ; i <= arrayA.Length - 1; i++)

             if (!arrayAIdea.Equals(arrayBIdea)) return false;

       return true;

}

Patrick Mac Kay
Noviembre 2004.

by pmackay
Filed under:

Comments

# pmackay said on Thursday, May 26, 2005 3:10 PM

Hola saludos me interesa mucho este tema ya que en este area me he desenvuelto mucho desde chavo le agradeceria al autor de esta informacion me pueda explicar un poco mas sobre como usar las contraseñas hash ya que he saca unas cuantas pero al intentra utilizarlas me es un poco dificil ya que aun no entiendo que es enrealidad los bugs que abren o que bulnerabilidades puedo ver y usar saludos ATTE
nando

# pmackay said on Wednesday, August 24, 2005 10:26 AM

Hola. Me llamo Eugenio y llevo unos meses estudiando VB.NET, e traducido el código que ahi pones a VB y me interesa poder desencripatar, para mis aplicaciones. Me podías envíar a mi correo (eecsaky@hotmail.com) el código para desencriptar.

Un saludo, eecsaky

# pmackay said on Wednesday, August 24, 2005 3:09 PM

Eugenio,

la encriptación Hash no es posible de desencriptarla. Si tu buscar un algoritmo que puedas encriptar y desencriptar de forma segura, debes utilizar algoritmos simetricos. Te recomiendo que utilices Rijndael.

Fijate en este otro post : http://msmvps.com/pmackay/archive/2004/11/27/21085.aspx

Saludos.

Patrick.

# pmackay said on Tuesday, September 20, 2005 12:32 PM

Muy explicativo, sin embargo quería saber si es posible que tengas un ejemplo en VB Net. Gracias por tu aporte. ulatealejandro@yahoo.com

# pmackay said on Sunday, October 23, 2005 3:46 PM

entendi tu explicacion , desde pequeño me a llamadola atencion el tema de , desecriptar ya q me gusta saber que hay detras de lo que los otros no ven, no me gusta dañar, solo por curiosidad empeze, pero ahora , mesiento demaciado atraido por este tema , tengoalgunos soft pero noson presisos ( Al 100%), pero confiables, me gustaria q me mandaras algunos si es q llegas a tener o tienes , ok ciao

ATTE

alexander b.

genio.tan@gmail.com

# Sixaxis said on Monday, August 13, 2007 6:57 PM

Olaa queria saber si un correo de hotmail se puede desencriptar?

# pmackay said on Monday, August 13, 2007 8:18 PM

Me imagino que te refieres a la contraseña de una cuenta de hotmail, que corresponde a una cuenta de live. En ese caso, las personas de live te podrán responder mejor esa pregunta.

Saludos,

Patrick

# jac said on Friday, October 05, 2007 4:19 AM

Hola, mi gran dilema...¿Cuál creeis que sería el mejor modo de almacenar el salt? Si lo almacenas en la base de datos, el riesgo sería el mismo en caso de que accediera a ella, pues al tener el salt y el hash, el proceso para crackearlo sería el mismo que si no incluyes un salt a la encriptación y no tendría dificultad añadida; el usuario no puede recordar el salt porque es randómico y lo olvidaría; la aplicación no puede contenerlo porque sería inútil.

¿¿Es realmente útil el salt??

# pmackay said on Friday, October 05, 2007 8:46 AM

Jac,

El salt no fue concebido para dar la seguridad que tú mencionas. Si alguien tiene acceso a la base de datos, el salt no proveerá mucha más seguridad.

La utilidad del salt se puede medir en al menos 2 aspectos:

1.- Contraseñas iguales tendrán un hash diferente ya que el salt hará que no sean iguales (las contraseñas finales). Aunque los usuarios ingresen la parte que es igual, tú le concatenas la parte que hace la diferencia.  En este caso, si se llega a comprometer una contraseña, ya sea porque el usuario la dijo o la obtuvieron ilícitamente, no se podrá comparar el hash y decir que estas otras contraseñas son iguales.

2.- Evitar ataques con Rainbow tables. Estas tablas almacenan valores precalculados de contraseña y hash. Es decir, para una contraseña, su hash correspondiente (no tengo mayores conocimientos de rainbow tables, ni como almacenan los hash ni qué algoritmos de hash utilizan). Si utilizas salt, todos los hash precalculados de la tabla no sirven.

¿Se entiende?

Te recomiendo la lectura de este link para que veas más ejemplos.

www.microsoft.com/.../sm1005.mspx

Saludos,

Patrick

# pmackay said on Friday, October 05, 2007 8:48 AM

y respondiendo la otra pregunta, lo puedes alamcenar como un campo de texto en la tabla de usuarios. No es necesario protegerlo más que eso.

Patrick.

# andrea said on Thursday, May 29, 2008 6:12 PM

Hola:mi problema es que desde mi laptop ( y no desde otras pc) no puedo acceder a mi cuenta de hotmail o yahoo, ya que luego de poner la contrasenia aparece un mensaje de error: HTTP 400 LA PAGINA WEB NO PUEDE SER ENCONTRADA y un candado aparece al lado de la barra de direcciones de IE.En otras ocasiones pude acceder a mi cuenta pero al clickear para leer los mails, vuelve a aparecer el mensaje de error.

Que tengo que hacer?, (es solo desde esta maquina y no sucede con otras)

Gracias por la pronta respuesta

# pmackay said on Friday, May 30, 2008 4:01 PM

Andrea,

fíjate que la fecha y hora esté correcta en tu equipo.

Saludos,

# andrea said on Saturday, May 31, 2008 4:26 PM

PMACKAY: SI, LA FECHA Y HORA ESTAN CORRECTAS.lO LLAMATIVO ES QUE ESTO EMPEZÓ A SUCEDER LUEGO QUE ME INSTALARAN EL MODEM.aNTES NO TENÍA PROBLEMAS, AUNQUE EN LA COMPANIA QUE ME LO INSTALO DICEN QUE NO TIENE NADA QUE VER CON ELLOS, Y QUE PODRIA SER UN TEMA DEL EXPLORADOR, POR LO QUE ME SUGIRIERON HACERLO CON MOZILLA.tAMPOCO SE SOLUCIONO EL PROBLEMA.

sIGO A LA ESPERA DE AYUDA!!!!!!gRACIAS

# carlos said on Thursday, September 18, 2008 6:25 PM

Hola que tal esta muy interesante esta algoritmo y me interesa bastante ya que estoy trabajando con tranferir algunos datos incriptados te agradeceris si me pudieras mandar el codigo para desencriptar a mi correo grax!!! eerm_15@hotmail.com

# pmackay said on Thursday, September 18, 2008 10:48 PM

Carlos,

todo lo que necesitas está publicado en este post, con más información y ejemplos para copiar.

msmvps.com/.../post28.aspx

Saludos,

Patrick

Leave a Comment

(required) 
(required) 
(optional)
(required)