Generar hash SHA-256, SHA-1, SHA-512 y MD5 de un texto o un archivo

Escribe un texto o elige un archivo y la herramienta calcula su hash SHA-256, SHA-512, SHA-1 y MD5, en hexadecimal y en Base64. Pega el hash que publica una página de descarga y te dirá si coincide: así sabes que el archivo llegó entero y sin cambios. Todo se calcula en tu navegador: ni el texto ni el archivo se envían a ningún sitio, aunque sea de cientos de MB.

Para guardar contraseñas no sirve un hash como estos. SHA-256 y MD5 son rápidos a propósito, y eso permite probar miles de millones de contraseñas por segundo. Para contraseñas se usan funciones lentas diseñadas para ello, como Argon2id, scrypt o bcrypt.

Qué es un hash

Una función hash convierte cualquier dato, de un byte o de varios GB, en un resumen de tamaño fijo: 256 bits (64 cifras hexadecimales) en SHA-256. Tiene tres propiedades que la hacen útil:

  • Siempre da lo mismo con lo mismo: el mismo archivo da el mismo hash en cualquier equipo y con cualquier programa.
  • Un cambio mínimo lo cambia todo: el SHA-256 de Hola, mundo empieza por 02e1557c; el de Hola, Mundo, con una sola mayúscula, por 7f6bc9c1; y el de Hola, mundo con un salto de línea al final, por 646a52c7.
  • No se puede invertir: a partir del hash no se puede recuperar el texto, y con un algoritmo seguro tampoco se pueden fabricar dos datos distintos con el mismo hash (una colisión).

Verificar un archivo descargado

Muchos proyectos publican junto a la descarga su SHA-256, a veces en un archivo SHA256SUMS. Elige el archivo en la herramienta, pega el hash publicado en «Hash para comparar» y mira si coincide. También puedes hacerlo desde la terminal:

  • Linux: sha256sum archivo.iso, o sha256sum -c SHA256SUMS para comprobar la lista entera.
  • macOS: shasum -a 256 archivo.dmg.
  • Windows (PowerShell): Get-FileHash archivo.exe, que usa SHA-256 por defecto, o Get-FileHash archivo.exe -Algorithm MD5.

Si el hash coincide, el archivo es idéntico al que se usó para calcular el hash publicado. Si la página de descarga y el hash vienen del mismo servidor y alguien lo ha comprometido, puede haber cambiado los dos: para protegerse de eso existen las firmas digitales, como las de GPG.

MD5, SHA-1, SHA-256 y SHA-512

  • MD5 (128 bits, RFC 1321): roto. Desde 2004 se conocen colisiones, y hoy se fabrican en segundos en un portátil. Según la RFC 6151, no se debe usar donde haga falta resistencia a colisiones, como las firmas digitales. Sigue sirviendo para detectar errores de transmisión, no manipulaciones.
  • SHA-1 (160 bits): roto. En 2017, investigadores de Google y del CWI de Ámsterdam publicaron SHAttered, la primera colisión real: dos PDF distintos con el mismo SHA-1. El NIST anunció en diciembre de 2022 que debe dejarse de usar antes del 31 de diciembre de 2030. Git todavía lo usa para nombrar los commits, con protecciones adicionales.
  • SHA-256 (256 bits, familia SHA-2, FIPS 180-4): el estándar actual para verificar descargas, firmar software y en certificados TLS. No se le conocen ataques prácticos.
  • SHA-512 (512 bits, también SHA-2): más largo. En procesadores de 64 bits que no tienen instrucciones específicas para SHA-256, suele calcularse incluso más deprisa que SHA-256.

Con archivos, la herramienta calcula los SHA con crypto.subtle, la criptografía integrada en el navegador, que es muy rápida; MD5 no está en ella y se calcula en JavaScript. Para textos cortos, o si el navegador no ofrece crypto.subtle, usa su propia implementación en JavaScript, que da exactamente el mismo resultado.

Calcular un hash en Python

Con hashlib, leyendo el archivo por trozos para no cargarlo entero en memoria:

import hashlib
import hmac
import tempfile

texto = "Hola, mundo"
for nombre in ["md5", "sha1", "sha256", "sha512"]:
    print(f"{nombre:7}", hashlib.new(nombre, texto.encode("utf-8")).hexdigest())


def hash_archivo(ruta, algoritmo="sha256"):
    """Lee el archivo por trozos de 1 MB: sirve igual para uno de varios GB."""
    h = hashlib.new(algoritmo)
    with open(ruta, "rb") as f:
        for trozo in iter(lambda: f.read(1024 * 1024), b""):
            h.update(trozo)
    return h.hexdigest()


with tempfile.NamedTemporaryFile(delete=False) as f:          # un archivo de prueba
    f.write(b"\x00" * 3_000_000)

publicado = "35BCE4EAE54EC8E6CC2868BAA8D157914D6AE2858811B4CC0C078C94460FA26F"   # el de la página de descarga
calculado = hash_archivo(f.name)
print(calculado)
# compare_digest compara en tiempo constante; aquí basta con ==, pero es buena costumbre
print("Coincide" if hmac.compare_digest(calculado, publicado.lower()) else "No coincide: el archivo no es el publicado")
$ python3 hash.pymd5     94a02d23857fce110414a2d92710f2d0
sha1    a72813313c08f263a7a5e7da3ed3919efeccddff
sha256  02e1557c91cd1834cce0b9a824283e1cedf497ed0037338a284aaa70b68b536e
sha512  afa5804b6f40cfd9b4f0ea7bf77043a7df0cd81d20b13041f0369c9bcc9060a8f45c58bf639d4002fe2db19066314a2ca2c4a59764854620b54e865a5fb11498
35bce4eae54ec8e6cc2868baa8d157914d6ae2858811b4cc0c078c94460fa26f
Coincide

Otras herramientas para desarrolladores: codificar y decodificar Base64 y URL, formateador de JSON, decodificador de JWT y conversor de fechas Unix. Todas, en decodigo.com/herramientas.

Algoritmos: FIPS 180-4 (SHA-1, SHA-256, SHA-512) y RFC 1321 (MD5). Seguridad de MD5: RFC 6151. Colisión de SHA-1: SHAttered (23 de febrero de 2017). Retirada de SHA-1: NIST, 15 de diciembre de 2022. Contraseñas: OWASP Password Storage Cheat Sheet. La implementación en JavaScript y la de crypto.subtle se compararon con hashlib de Python en 3,269 entradas, de 0 bytes a 2.5 MB, con los cuatro algoritmos: coinciden en todas.