Universidad de Cundinamarca – Extensión Chía
Ingeniería de Sistemas
Juan Manuel Fonce Camacho
Gustavo Adolfo Jiménez Vera
Jorge Duban Bernal Cardenas
Informe Académico
Hash Seguro Java
Línea de Profundización I
Ing. Misael Fernando Perilla Benítez
2020
Contenido
Hash seguro Java - MD5, SHA256, SHA512, PBKDF2, BCrypt, SCrypt........................................................2
1. Seguridad de contraseña simple usando el algoritmo MD5........................................................2
2. Seguridad de contraseña media mediante algoritmos SHA........................................................5
3. Seguridad de contraseña avanzada usando el algoritmo PBKDF2WithHmacSHA1...............6
4. Hash de contraseña más seguro utilizando algoritmos bcrypt y scrypt...................................10
5. Conclusiones.................................................................................................................................10
6. Bibliografía...................................................................................................................................11
Hash seguro Java - MD5, SHA256, SHA512, PBKDF2, BCrypt, SCrypt
Un hash de contraseña segura es una secuencia encriptada de caracteres obtenida después de
aplicar ciertos algoritmos (los cuales veremos más adelante) y manipulaciones en la contraseña
que se da por el usuario ya que esta por lo general es muy débil e insegura debió a su facilidad de
adivinar.
1. Seguridad de contraseña simple usando el algoritmo MD5
Este algoritmo es una función hash criptográfica que produce un valor hash de 128 bits.
La idea básica de esta función es mapear conjuntos de datos de longitud variable a conjuntos de
datos de longitud fija. Para llevar esto acabo, el mensaje de entrada se divide en bloques de 512
bits, luego se agrega un relleno al final para que su longitud se pueda dividir por 512. Después
estos bloques son procesados por el algoritmo MD5, que opera en un estado de 128 bits como ya
se mencionó, y el resultado será un valor hash de 128 bits. Terminando de aplicar el algoritmo
MD5, el hash generado suele ser un número hexadecimal de 32 dígitos.
Al tomar el código dado, he cambiado el mensaje a cifrar por mi nombre completo y luego lo
ejecute. Como resultado se obtuvo lo siguiente:
Como se puede ver, el hash generado de mi nombre con MD5 es
1b25b2e9e6327bbad600080eb0212603, el cual efectivamente es un numero hexadecimal de 32
dígitos. Pero al quitarle la última letra se obtiene el siguiente hash:
El hash generado es b30d8552c17880aef80592f177c4bcbe en el cual podemos notar que es un
numero hexadecimal completamente distinto, pero de la misma longitud.
Por otro lado, el código pues ya viene según el numero de bytes generados para MD5, pero si
cambiamos por ejemplo en donde se hace la conversión al formato hexadecimal y alteramos
0x100 a 0x10 obtendremos un hash de 15 dígitos:
Hash generado: 463291f93285df, consecutivamente si se cambiara a 0x10 se generaría un hash
de 16 dígitos.
En lo entendido para estos cifrados, el hash generado es aleatorio.
Cabe resaltar que este algoritmo hash genera hashes muy débiles pero la ventaja es que es rápido
y fácil de implementar, aunque esto lleva a que es susceptible a ataques de diccionario y de
fuerza bruta. Por otro lado, MD5 no es resistente a colisiones lo que significa que diferentes
contraseñas pueden llegar a resultar en el mismo hash.
Para lo anterior, el algoritmo MD5 se puede hacer más seguro usando salt, el cual lo que hace es
generar datos aleatorios los cuales se utilizan como una entrada adicional a una función
unidireccional que codifica la contraseña dada. Para esto se necesita usar SecureRandom que
permite crear buenas Salts. En Java soporta SHA1PRNG que es un algoritmo generador de
numero pseudoaleatorios criptográficamente fuerte que esta basado en el algoritmo de resumen
de mensajes SHA-1.
Implementado el código agregándole Salt usando SHA1PRNG:
Como podemos ver se puso el mismo texto (mi nombre) y como resultado cambia el hash
generado. El primer hash es el generado y el segundo es la verificación del hash ya generado.
Si lo comparamos con el primer hash resultante (1b25b2e9e6327bbad600080eb0212603), se
nota que cambia completamente:
0d46dd6d8edbb1eddfd03a0720ab0c7d.
Hay que resaltar que si se ejecuta el código nuevamente sin cambiar la contraseña el hash
generado va a ser distinto.
2. Seguridad de contraseña media mediante algoritmos SHA
Secure Hash Algorithm (SHA) es una familia de funciones de hash criptográficas. Este es muy
similar al anterior visto (MD5), la diferencia es que los hashes generados son más fuertes pero de
igual manera puede llegar a generar hashes iguales con entradas diferentes aunque en SHA las
posibilidades de que se de esto son menores o muy raras.
En Java hay 4 implementaciones de este algoritmo; cada uno generan hashes de diferente
longitud:
SHA-1 (el más simple - Hash de 160 bits)
SHA-256 (más fuerte que SHA-1 - Hash de 256 bits)
SHA-384 (más fuerte que SHA-256 - 384 bits Hash)
SHA-512 (más fuerte que SHA-384 - 512 bits Hash)
Lógicamente, el hash más largo es más difícil de romper.
HASH SHA-1: b7000d59584551740499e52639c44e20773341d9
HASH SHA-256: db0085ede0a50c4516ff237e10f6eb497ca9e91124ab023521380ae4de89ad6d
HASH SHA-384:
65ac6e110da7c6b6965e1f0f17c070f2726f6dd953c4794808b8a95eb7bffd369faa6e8d2f1cd1f9e8
9a149f7026882e
HASH SHA-512:
199dc4ed797d0190dcafa430d93d54ee1357aa0ff67f5c5618301e17c642ecaf166f5f91e63cac36f1
b82f5c31e201950308b11a2c92ad13db54ebffd81074c4
Como podemos ver, implementado el código y cambiando la contraseña o texto que se quiere
cifrar por mi nombre, tenemos distintos hashes generados por cada implementación de SHA.
Cabe resaltar que los hashes resultantes van a ser distintos si se vuelve y se ejecuta el código sin
cambiar nada puesto que se está usando Salt manejando SHA1PRNG como se hizo
anteriormente.
3. Seguridad de contraseña avanzada usando el algoritmo PBKDF2WithHmacSHA1
Actualmente los hardware son muy rápidos lo cual hace que un ataque de fuerza bruta usando un
diccionario y tablas de arco iris se pueda descifrar una contraseña en menos o mas tiempo. Por
esto se busca hacer que el ataque sea mas lento para minimizar el daño; como resultado se genera
algunos algoritmos intensivos de CPU como PBKDF2, Bcrypt o Scrypt.
Para el ejemplo de implementación de hash Java PBKDF2WithHmacSHA1:
Este resultado es confuso, pero nuestro primer numero (1000) es el número de interacciones que
ponemos. Luego viene el Salt de 32 dígitos que ya hemos implementado anteriormente y por
último viene el hash que estamos trabajando en este ejemplo que es el PBKDF2WithHmacSHA,
es un cifrado muy grande, pero se puede reducir, aunque lo ideal es que sea más grande para que
la función hash sea lo suficientemente lenta para impedir los ataques, pero a la vez lo
suficientemente rápida como para no causar un retraso notable al usuario.
Al cambiar los números que se multiplican se puede hacer mas grande o mas pequeño el hash
generado.
Luego se necesita tener una función que pueda usarse para validar la contraseña nuevamente
cuando el usuario regrese e inicie sesión. Para lo cual:
Si observamos bien la imagen anterior ahora nos aparece dos resultados mas que son booleanos
(true y false), esto para determinar si la contraseña es efectivamente la misma. Como notamos no
lo es ya que en son distintos, por tal razón ambas validaciones dan como resultado false.
Es esta imagen (anterior) ya notamos que en los espacios de la contraseña en el código ya he
cambiado, y en la primera validación de true puesto que es coincidente con la contraseña
establecida pero la segunda no lo es.
Por terminado al poner la contraseña correcta en ambas validaciones notamos que efectivamente
nos da true en ambas ya que si se observa bien en la imagen tanto como la contraseña
establecida y las validaciones son exactamente la misma.
4. Hash de contraseña más seguro utilizando algoritmos bcrypt y scrypt
Los conceptos de bcrypt son parecidos al concepto anterior como en PBKDF2, pero Java no
tiene ningún soporte incorporado para el algoritmo bcrypt para hacer que el ataque sea más lento,
pero aún puede encontrar una implementación de este tipo en la descarga del código fuente.
Como ejemplo de bcrypt con salt:
Trabajemos el código de uso de muestra (BCrypt.java está disponible en código fuente).
Al descargar el código fuente proporcionado y ejecutarlo como resultado tenemos lo anterior,
aunque sinceramente la estructura de es mucho más grande.
5. Conclusiones
(Proporcionadas)
1. El almacenamiento de la contraseña de texto con hash es lo más peligroso para la
seguridad de las aplicaciones en la actualidad.
2. MD5 proporciona hash básico para generar un hash de contraseña seguro. Agregar
sal lo hace aún más fuerte.
3. MD5 genera hash de 128 bits. Para hacerlo más seguro, use el algoritmo SHA que
genera hashes de 160 bits a 512 bits de longitud. 512 bits es el más fuerte.
4. Incluso las contraseñas seguras con hash SHA se pueden descifrar con los rápidos
hardware actuales. Para superar eso, necesitará algoritmos que puedan hacer que
los ataques de fuerza bruta sean más lentos y minimizar el impacto. Estos
algoritmos son PBKDF2, BCrypt y SCrypt.
5. Piense bien antes de aplicar el algoritmo de seguridad adecuado.
6. Bibliografía
https://howtodoinjava.com/java/java-security/how-to-generate-secure-password-hash-md5-sha-
pbkdf2-bcrypt-examples/