0Pricing
Java Academy · Lección

Hash criptográfico con MessageDigest

Calcule hashes de contraseñas con SHA-256, añada salt para evitar ataques con tablas arcoíris y compare los resúmenes de forma segura.

Hash criptográfico con MessageDigest es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

¿Qué es el hashing criptográfico?

Una función hash criptográfica transforma datos de cualquier tamaño en un resumen de tamaño fijo. Es unidireccional (no se puede invertir), determinista y resistente a colisiones. Se utiliza para almacenar contraseñas, garantizar la integridad de los datos y crear firmas digitales.

API MessageDigest

MessageDigest.getInstance("SHA-256") devuelve un generador de hash SHA-256. Llame a digest(bytes) para calcular el hash y obtener un array de bytes.

MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] hash = md.digest("password123".getBytes(StandardCharsets.UTF_8));
String hex = HexFormat.of().formatHex(hash);
System.out.println(hex); // 64-char hex string

Algoritmos comunes

El JDK admite: MD5 (roto; nunca lo utilice con fines de seguridad), SHA-1 (obsoleto por motivos de seguridad), SHA-256 (estándar), SHA-512 (más robusto) y SHA3-256 (moderno). Utilice siempre SHA-256 o SHA-512 en código nuevo.

MessageDigest.getInstance("SHA-256");  // recommended
MessageDigest.getInstance("SHA-512");  // stronger
MessageDigest.getInstance("SHA3-256"); // SHA-3 family
// Never: MessageDigest.getInstance("MD5"); // cryptographically broken

Conversión de un hash a una cadena hexadecimal

El resultado en forma de array de bytes debe convertirse en una cadena hexadecimal para almacenarlo o compararlo. Utilice HexFormat (Java 17+) o String.format en versiones anteriores.

// Java 17+:
String hex = HexFormat.of().formatHex(hash);
// Older Java:
StringBuilder sb = new StringBuilder();
for (byte b : hash) sb.append(String.format("%02x", b));
String hex = sb.toString();

La sal: cómo derrotar a las tablas arcoíris

Una tabla arcoíris relaciona contraseñas comunes con sus hashes. Añadir una sal incorpora un valor aleatorio a cada contraseña antes de calcular el hash, lo que inutiliza las tablas arcoíris. Almacene la sal junto con el hash.

SecureRandom random = new SecureRandom();
byte[] salt = new byte[16];
random.nextBytes(salt);
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(salt);
byte[] hash = md.digest("password".getBytes(StandardCharsets.UTF_8));
// Store: Base64.encode(salt) + ":" + Base64.encode(hash)

Hashing de contraseñas: utilice BCrypt

SHA-256 con una sal es mejor que SHA-256 sin más, pero sigue siendo rápido: un atacante puede probar miles de millones de combinaciones por segundo. Utilice una KDF lenta: BCryptPasswordEncoder (Spring Security), PBKDF2 o Argon2 para las contraseñas.

// Spring Security — proper password hashing:
PasswordEncoder encoder = new BCryptPasswordEncoder(12); // cost factor 12
String hash = encoder.encode("password123");
boolean match = encoder.matches("password123", hash); // true

Comprobación de la integridad de archivos

Calcule el hash de un archivo para detectar corrupción o manipulación. Compare el hash calculado con una referencia conocida como válida.

MessageDigest md = MessageDigest.getInstance("SHA-256");
try (InputStream is = Files.newInputStream(Path.of("app.jar"))) {
    byte[] buf = new byte[8192];
    int n;
    while ((n = is.read(buf)) > 0) md.update(buf, 0, n);
}
String hash = HexFormat.of().formatHex(md.digest());
System.out.println("SHA-256: " + hash);

Comparación segura de hashes

Utilice MessageDigest.isEqual() para realizar una comparación en tiempo constante y evitar ataques de temporización. No utilice nunca String.equals() para comparar hashes.

byte[] expected = computeHash(storedHash);
byte[] actual   = computeHash(inputPassword);
boolean match = MessageDigest.isEqual(expected, actual); // constant-time

Encadenamiento de actualizaciones

Llame varias veces a md.update(bytes) antes de md.digest() para calcular el hash de datos que llegan por fragmentos (streaming).

MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update("part1".getBytes());
md.update("part2".getBytes());
byte[] hash = md.digest(); // hash of "part1" + "part2"

Codificación de hashes para su almacenamiento

Almacene los hashes binarios como cadenas Base64 (más cortas que las hexadecimales) o hexadecimales. Base64 utiliza 43 caracteres para SHA-256, frente a los 64 de la representación hexadecimal. Ambas opciones son correctas; sea coherente.

byte[] hash = md.digest(data);
String base64 = Base64.getEncoder().encodeToString(hash); // 44 chars (with padding)
String hex    = HexFormat.of().formatHex(hash);           // 64 chars

DigestInputStream para streaming

Envuelva un InputStream con DigestInputStream para calcular el hash mientras lee, evitando cargar el archivo completo en memoria.

MessageDigest md = MessageDigest.getInstance("SHA-256");
try (DigestInputStream dis = new DigestInputStream(Files.newInputStream(path), md)) {
    dis.transferTo(OutputStream.nullOutputStream());
}
String hash = HexFormat.of().formatHex(md.digest());

Comprobación rápida

¿Por qué no se recomienda SHA-256 con sal para almacenar contraseñas?

Resumen

Utilice MessageDigest.getInstance("SHA-256") para comprobar la integridad de los datos. Añada siempre una sal a las contraseñas, pero utilice BCrypt o Argon2 para almacenarlas, no SHA sin más. Utilice una comparación en tiempo constante (MessageDigest.isEqual) para evitar ataques de temporización.

Preguntas frecuentes

¿La lección «Hash criptográfico con MessageDigest» es gratis?

Sí — el texto completo de «Hash criptográfico con MessageDigest» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Hash criptográfico con MessageDigest»?

Calcule hashes de contraseñas con SHA-256, añada salt para evitar ataques con tablas arcoíris y compare los resúmenes de forma segura. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Hash criptográfico con MessageDigest»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Hash criptográfico con MessageDigest
  2. Cifrado simétrico AES
  3. HMAC-SHA256 para la integridad de mensajes
  4. JWT: estructura, creación y verificación
← Volver a Java Academy