Saltar al contenido
AldeaCode Logo
Generador de Hash / PHP Desarrollador 100% local

Generar hashes en PHP: hash(), hash_file(), hash_hmac() y password_hash()

PHP trae todo lo necesario para hashing en la stdlib. La función hash() recibe un nombre de algoritmo y un string, devuelve hex. La trampa es usarla para contraseñas, que no es para lo que está.

hash() es la función general

hash($algo, $data) devuelve el digest hex de $data bajo $algo. El primer argumento es un nombre del registro de algoritmos: 'sha256', 'sha1', 'md5', 'sha3-256', 'xxh3', y docenas más. hash_algos() devuelve la lista completa disponible en tu build de PHP. La lista creció bastante con PHP 8.1, que añadió xxh32, xxh64 y xxh3.

Pasa un tercer argumento true para obtener bytes crudos en lugar de hex. Importa cuando metes el digest en otro protocolo binario o cuando el hex te dobla el almacenamiento. Para cabeceras HTTP y columnas de base de datos, deja el default y guarda el string hex.

hash() es rápida, sin allocations para inputs pequeños, y la herramienta correcta para direccionamiento por contenido, comprobaciones de integridad, generación de ETag y claves de caché. Es la herramienta incorrecta para contraseñas.

Nunca uses md5 o sha1 para contraseñas

MD5 y SHA-1 están diseñados para ser rápidos. Las GPUs modernas calculan miles de millones de hashes MD5 por segundo. Una base de datos filtrada con hashes MD5 de contraseñas es una base de datos filtrada con contraseñas en claro al rato que el atacante se toma el café. SHA-256 es más lento por hash pero sigue siendo rápido como para que un brute force con GPU rompa cualquier contraseña por debajo de doce caracteres en pocas horas.

Hashear contraseñas necesita una función lenta, memory-hard: bcrypt, scrypt o argon2. La password_hash() de PHP envuelve estas y elige bcrypt por defecto, con argon2id disponible vía PASSWORD_ARGON2ID. La función genera su propio salt, codifica el algoritmo y los parámetros en el resultado, y password_verify() los lee de vuelta. Tú nunca guardas el salt, tú nunca eliges el coste salvo que hayas hecho benchmark del hardware destino.

Si ves código que llama a hash('sha256', $password . $salt) para guardar contraseñas, reemplázalo. El arreglo es una migración puntual: en el próximo login, verifica contra el hash viejo, luego re-hashea con password_hash() y sobreescribe la columna.

hash_hmac() para hashes autenticados

Un HMAC ata un hash a una clave secreta. Sirve para firmas de webhook, firma de peticiones de API, y cualquier sitio donde necesitas probar que un mensaje viene de alguien que tiene el secreto compartido. La firma es hash_hmac($algo, $data, $key).

El argumento de la clave es el secreto compartido como string crudo. No lo codifiques en hex antes de pasarlo salvo que la spec que estás implementando lo diga. Los webhooks de GitHub pasan el secreto directo. Los webhooks de Stripe pasan el secreto directo. Codificar mal la clave produce una firma de aspecto válido pero incorrecta, y vas a pasar una hora preguntándote por qué falla la verificación.

Compara el resultado con hash_equals(), nunca con ==. El operador de doble igual hace corto-circuito en el primer byte que no coincide, filtra información de timing, y permite a un atacante remoto reconstruir la firma byte a byte tras unos miles de peticiones. hash_equals() es de tiempo constante.

hash_file() para archivos sin cargarlos

Para archivos de varios gigabytes, llamar a hash('sha256', file_get_contents($path)) reserva el archivo entero en memoria. hash_file($algo, $path) hace stream del archivo en chunks de tamaño fijo y produce el mismo digest con memoria constante.

Úsala para integridad de subidas, claves de deduplicación y direccionamiento por contenido. El digest hex es idéntico calculado en PHP, en OpenSSL o con sha256sum en línea de comandos, así que la verificación entre sistemas funciona sin coordinación.

Ejemplo completo

php
<?php
// 1. SHA-256 de un string (hex)
$digest = hash('sha256', 'hola mundo');
echo $digest, "\n";

// 2. SHA-256 de un archivo, en streaming
$fileDigest = hash_file('sha256', '/ruta/a/upload.bin');
echo $fileDigest, "\n";

// 3. HMAC para verificar firma de webhook
$expected = hash_hmac('sha256', $rawBody, $sharedSecret);
if (!hash_equals($expected, $signatureFromHeader)) {
    http_response_code(401);
    exit('Firma incorrecta');
}

// 4. Contraseñas: bcrypt por defecto, argon2id disponible
$hash = password_hash($plain, PASSWORD_BCRYPT, ['cost' => 12]);

if (password_verify($attempt, $hash)) {
    if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])) {
        $hash = password_hash($attempt, PASSWORD_BCRYPT, ['cost' => 12]);
        // persistir el nuevo $hash
    }
}

¿Solo necesitas el resultado?

Cuando necesitas un sha256 rápido de un string para un archivo de configuración o probar un webhook, pega la entrada en el generador de hash de aldeacode.com. La página calcula md5, sha1, sha256, sha384 y sha512 en tu navegador a la vez, sin subir nada, sin ida y vuelta a un servidor.

Abrir Generador de Hashes SHA →

Preguntas frecuentes

¿Qué algoritmo de hash uso en PHP para datos que no son contraseñas?

SHA-256 para casi todo. xxh3 si solo necesitas un hash no criptográfico para deduplicación en memoria o claves de caché y quieres velocidad. MD5 solo cuando una spec legacy lo exige.

¿Por qué password_hash() produce un output distinto cada vez?

Genera un salt aleatorio nuevo en cada llamada. El salt va embebido en el string de salida, así password_verify() lo lee de vuelta. Es el comportamiento deseado; hashes idénticos para contraseñas idénticas anularían el salting.

¿Cómo listo los algoritmos disponibles en mi PHP?

Llama a hash_algos() y haz var_dump del resultado. La lista depende del OpenSSL contra el que se compiló PHP. SHA-256, SHA-1 y MD5 siempre están; SHA-3 desde PHP 7.1; xxh3 desde PHP 8.1.