Los algoritmos de hashing criptográficos, cálculo de hashes con comandos de GNU/Linux y Java
Escrito por
el .
java
planeta-codigo
Enlace permanente
Comentarios
Los algoritmos de hashing criptográficos son fundamentales en la firma digital y criptografía, pero también tienen su utilidad por sí mismos para la comprobación de la integridad. Se basan en un algoritmo y funciones matemáticas que transforman un conjunto de bytes en un número binario de longitud fija que constituye el hash digital del contenido. Hay varios algoritmos de hashing criptográficos y en GNU/Linux varios comandos que permiten calcular y comprobar el hash de un archivo. En los lenguajes de programación como en el caso de Java se ofrecen clases y métodos para la generación y cálculo de hashes en los algoritmos soportados.
El cifrado o encriptación permite que solo el receptor del mensaje pueda leer los datos, la firma digital permite conocer que los datos han sido generados por quien los firma y al recibirlos no han sido modificados por una tercera persona. El cifrado y la firma digital utilizan claves para realizar el cifrado y para la firma digital.
El cifrado y la firma digital son operaciones muy importantes para garantizar la seguridad en multitud de ámbitos. Sin embargo, la utilización de claves añaden algo de complejidad que a veces no es necesaria, a veces utilizar simplemente un algoritmo de hashing es suficiente y más sencillo ya que no requiere la utilización de claves.
Contenido del artículo
Los algoritmos de hashing criptográficos
Los algoritmos de hashing transforman un conjunto arbitrario de bytes a una cadena binaria de bytes de longitud fija, dependiendo del algoritmo la longitud fija resultante es diferente, algunos generan como resultado un número de 160 bits y los más seguros llegando a 512 bits.
Una aplicación práctica de los algoritmos de hashing es para evitar guardar las contraseñas de los usuarios en la base de datos en texto plano en la que interviene un algoritmo de hashing, utilizando la técnica conocida como salted password hashing.
Aunque las redes actuales ofrecen un gran ancho de banda y una fiabilidad notable siguen considerándose un medio poco fiable, a veces fallan y generan errores en la transmisión como pérdida de paquetes o alteración del contenido aún con las medida implementadas en el algoritmo de transmisión de paquetes TCP utilizado de forma mayoritaria en internet.
Al descargar un archivo grande es útil que el creador adjunte el hash del contenido para comprobar su integridad una vez descargado. Comprobar la integridad proporciona dos garantías: que el contenido es el original y no ha sido modificado por un intermediario y que el archivo descargado no se ha corrompido en la descarga.
La seguridad de los algoritmos de cifrado se basan en que sea muy difícil encontrar la cadena original que produzca un determinado hash, que dada una cadena sea difícil encontrar otra cadena que produzca el mismo hash y que sea difícil que dos cadenas distintas produzcan el mismo hash. Otra de sus propiedades es que aún con el cambio de un bit en el contenido hasheado el hash resultante es muy diferente. También por seguridad son algoritmos que distribuyen de forma uniforme los hashes en todo el rango de posibles resultados.
Hay diferentes algoritmos de hashing criptográfico:
- MD5: genera números de 160 bits de longitud. Ya se considera un algoritmo de hashing poco seguro ya que con la capacidad de computación actual es posible encontrar un cadena de bytes que produzca el mismo hash.
- SHA-1: genera números de 160 bits de longitud. También se considera un algoritmo de hashing vulnerable pudiendo encontrar colisiones, encontrar un contenido que genere un determinado hash.
- SHA-2: es la segunda versión de SHA utilizando algoritmos y funciones criptográficas más seguras. También se conoce como SHA-224, SHA-256, SHA-384 o SHA-512 donde el número indica el número de bits de hash de resultado.
- SHA-3: es la última adición a los algoritmos SHA pero que es diferente de forma significativa en su estructuras internas a MD5, SHA-1 y SHA-2. También soporta diferentes longitudes de hash denominándose SHA3-224, SHA3-256, SHA3-384 o SHA3-512.
Comandos de GNU/Linux para el cálculo de hashes
El sistema operativo GNU/Linux ofrece varios comandos, uno para cada algoritmo, para utilizar y calcular los hashes de una cadena de texto o un archivo. Basta indicar el algoritmo y el contenido del que calcular su hash. En los siguientes comandos se calcula el hash de la siguiente supuesta contraseña generada con el gestor de contraseñas KeePassXC.
El resultado de los algoritmos de hashing es un número de un determinado número de bits, los hashes se representan como un número en base 16, lo que para un número de 512 bits da una cadena de 128 números hexadecimales.
|
|
|
|
El paquete sha3sum hay que instalarlo manualmente si no está instalado, los otros comandos generalmente están instalados por ser dependencia de otro.
Usar algoritmos de hashing con Java
Desde un lenguaje de programación de alto nivel como Java también puede ser útil utilizar algoritmos de hashing. Java incorpora una API e implementa de forma eficiente los estándares de hashing criptográficos para ser utilizados de forma fácil por los programas.
Listar algoritmos de hashing soportados por el JDK
Los algoritmos de hashing soportados dependen de la versión del JDK, en el JDK 9 se añadió el soporte para SHA-3. Es posible listar qué algoritmos de hashing soporta el JDK con el que se ejecuta un programa con el siguiente código a través de la clase Security.
|
|
|
|
Estos son los algoritmos de hashing soportados por el JDK 17.
|
|
Por el JDK 11.
|
|
Y por el JDK 8.
|
|
Calcular hashes con las clases del JDK de Java
La clase principal para calcular hashes criptográficos en Java es MessageDigest, se obtiene una instancia de la clase a partir del algoritmo que se desea utilizar para calcular el hash. La clase MessageDigest ofrece los métodos update para proporcionar los bytes del contenido sobre él que calcular el hash y para terminar el cálculo se utiliza el método digest.
|
|
|
|
El resultado es un array de bytes que hay que codificar en hexadecimal. En el JDK 17 se ha añadido la clase HexFormat que permite hacer la conversión fácilmente sin dependencias adicionales.
Si se desea calcular el hash de un flujo de InputStream u OutputStream la API de Java ofrece las clases DigestInputStream y DigestOuputStream. En este ejemplo se calcula el SHA de la imagen del medio de instalación de la distribución Arch Linux del que su hash se publica en la misma ubicación que la imagen ISO y en la página de descargas de Arch Linux.
|
|
Este es el hash calculado por con Java.
|
|
Calcular hashes con una librería de terceros
En caso de estar obligado a utilizar un JDK antiguo que no soporte alguno de los algoritmos de hashing hay que recurrir a una librería de terceros. Hay varias, entre ellas Bouncy Castle, Guava y Apache Commons.
El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:./gradlew run