Ir al contenido

HMAC

De Wikipedia, la enciclopedia libre
SHA-1 HMAC Generation.

En la criptografía, un HMAC (a veces expandido como código de autentificación de mensajes en clave-hash o código de autenticación de mensaje basado en hash) es una construcción específica para calcular un código de autentificación de mensaje (MAC) que implica una función hash criptográfica en combinación con una llave criptográfica secreta. Como cualquier MAC, puede ser utilizado para verificar simultáneamente la integridad de los datos y la autentificación de un mensaje. Cualquier función hash criptográfica, tales como SHA-2 o SHA-3, puede ser utilizada para el cálculo de un HMAC; el algoritmo MAC resultante se denomina HMAC-SHA2 o HMAC-SHA3 en consecuencia. La fuerza criptográfica del HMAC depende de la potencia criptográfica de la función de hash subyacente, el tamaño de su salida de hash y el tamaño y calidad de la llave.

Una función hash iterativa rompe un mensaje en bloques de un tamaño fijo e itera sobre ellos con una función de compresión. Por ejemplo, SHA-2 y SHA-3 operan en bloques de 512-bit. El tamaño de la salida de HMAC es el mismo que el de la función de hash subyacente (entre 224 y 512 bits en el caso de SHA3 dependiente de la configuración).

La definición y el análisis de la construcción HMAC se publicó por primera vez en 1996 por Mihir Bellare, Ran Canetti y Hugo Krawczyk,[1]​ que también escribió el RFC 2104. Asimismo, este documento define una variante llamada NMAC que rara vez, o nunca, se utiliza. FIPS PUB 198 generaliza y estandariza el uso de HMAC. HMAC-SHA1 y HMAC-MD5 se utilizan dentro de los protocolos IPsec y TLS pero no son seguros hoy día.

Definición (de RFC 2104)

[editar]

donde:

H es una función hash criptográfica,
K es una clave secreta rellena a la derecha con ceros adicionales al tamaño del bloque de entrada de la función hash, o el hash de la llave original si es más largo que el tamaño de bloque,
m es el mensaje a ser autenticado,
|| denota concatenación,
⊕ denota disyunción exclusiva (XOR),
opad es el relleno exterior (0x5c5c5c…5c5c, un bloque de largo hexadecimal constante),
ipad es el relleno interior (0x363636…3636, un bloque de largo hexadecimal constante).

Implementación

[editar]

El siguiente pseudocódigo muestra cómo se puede implementar HMAC. El tamaño del bloque es de 64 (bytes) cuando se utiliza una de las siguientes funciones hash: SHA-1, MD5, RIPEMD-128/160.[2]

function hmac (key, message)
    if (length(key) > blocksize) then
        key = hash(key) // llaves con más tamaño que el bloque se acortan al tamaño justo aplicando hash a esas llaves
    end if
    if (length(key) < blocksize) then
        key = key ∥ [0x00 * (blocksize - length(key))] // llaves más cortas que el tamaño del bloque se agrandan con ceros (donde  es la concatenación)
    end if
   
    o_key_pad = [0x5c * blocksize] ⊕ key // Cuando el tamaño del bloque es el de la función de hash subyacente
    i_key_pad = [0x36 * blocksize] ⊕ key // Donde ⊕ es el o exclusivo (XOR)
   
    return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) // Donde  es la concatenación
end function

El siguiente es una implementación en Python de HMAC-MD5:

#!/usr/bin/env python

from hashlib import md5

trans_5C = bytearray((x ^ 0x5c) for x in range(256))
trans_36 = bytearray((x ^ 0x36) for x in range(256))
blocksize = md5().block_size # 64

def hmac_md5(key, msg):
    if len(key) > blocksize:
        key = md5(key).digest()
    key = key + bytearray(blocksize - len(key))
    o_key_pad = key.translate(trans_5C)
    i_key_pad = key.translate(trans_36)
    return md5(o_key_pad + md5(i_key_pad + msg).digest())

if __name__ == "__main__":
    #  Este es un ejemplo del apéndice de la RFC 2104    
    h = hmac_md5(b"Jefe", b"what do ya want for nothing?")
    print(h.hexdigest()) # 750c783e6ab0b503eaa86e310a5db738

Python incluye un módulo hmac,[3]​ por lo que la función anterior puede ser reemplazada por una versión más corta.

import hmac
from hashlib import md5

def hmac_md5(key, msg):
    return hmac.HMAC(key, msg, md5)

El siguiente código es una implementación en PHP de HMAC-SHA1:

function sha1_hmac($key,$data,$blockSize=64,$opad=0x5c,$ipad=0x36) {

    // Llaves de más tamaño que el bloque se acortan
    if (strlen($key) > $blockSize) {
        $key = sha1($key,true);	
    }
    
    // Llaves más cortas que el tamaño de bloque son rellenadas con ceros a la derecha (concatenado)
    $key       = str_pad($key,$blockSize,chr(0x00),STR_PAD_RIGHT);	
    $o_key_pad = $i_key_pad = '';
    
    for($i = 0;$i < $blockSize;$i++) {
        $o_key_pad .= chr(ord(substr($key,$i,1)) ^ $opad);
        $i_key_pad .= chr(ord(substr($key,$i,1)) ^ $ipad);
    }
    
    return sha1($o_key_pad.sha1($i_key_pad.$data,true),true);
}

$hmac = sha1_hmac('key','The quick brown fox jumps over the lazy dog');

PHP incluye una función HMAC,[4]​ por lo que el ejemplo anterior puede ser reemplazado por una versión más corta.

<?php
hash_hmac('sha1', 'The quick brown fox jumps over the lazy dog', 'key');

La siguiente es una implementación usando QCryptographicHash de Qt

QByteArray hmacSha256(QByteArray key, const QByteArray& message) {
	const int blocksize = 64;
	if (key.length() > blocksize)
		QCryptographicHash::hash(key, QCryptographicHash::Sha256);

	while (key.length() < blocksize)
		key.append('\0');

	QByteArray o_key_pad('\x5c', blocksize);
	o_key_pad.fill('\x5c', blocksize);

	QByteArray i_key_pad;
	i_key_pad.fill('\x36', blocksize);

	for (int i=0; i<blocksize; i++) {
		o_key_pad[i] = o_key_pad[i] ^ key[i];
		i_key_pad[i] = i_key_pad[i] ^ key[i];
	}

	return QCryptographicHash::hash(o_key_pad 
		+ QCryptographicHash::hash(i_key_pad + message, QCryptographicHash::Sha256), QCryptographicHash::Sha256);
}

El siguiente es un ejemplo usando Node.js integrado en el módulo criptográfico utilizando HMAC-SHA1:

var crypto = require('crypto'),
    hmac = crypto.createHmac('sha1', 'Shared Secret');
 
hmac.update(message);
 
var hmacHash = hmac.digest('hex');

Principios de diseño

[editar]

El diseño de la especificación HMAC fue motivada por la existencia de ataques contra los mecanismos más triviales de la combinación de una llave con una función hash. Por ejemplo, se podría suponer la misma seguridad que HMAC proporciona podría lograrse con MAC = H(llavemensaje). Sin embargo, este método adolece de un grave defecto: con la mayoría de las funciones hash, es fácil añadir datos al mensaje sin conocer la llave y obtener otra MAC válida ("ataque longitud de extensión"). La alternativa, añadiendo la clave utilizando MAC = H(mensajellave), sufre del problema de que un atacante que puede encontrar una colisión en la función hash tiene una colisión en el MAC (como dos mensajes M1 y M2 obteniéndose el mismo hash proporcionará la misma condición de arranque de la función hash antes de obtener el hash de la llave adjunta, por lo tanto, el hash final será el mismo). Usar MAC = H(llavemensajellave) es mejor, pero varios artículos de seguridad han sugerido vulnerabilidades con este enfoque, incluso cuando se utilizan dos claves diferentes.[1]

No se conocen extensiones de ataques en contra de la actual especificación HMAC que se define como H(llaveH(llavemensaje)) porque la aplicación externa de la función de hash marca el resultado intermedio del hash interno. Los valores de ipad y opad no son críticos para la seguridad del algoritmo, pero se define de tal manera que tengamos una gran distancia de Hamming entre sí y para que las llaves interior y exterior tengan menos bits en común. La reducción de la seguridad de HMAC no les obliga a ser diferentes en al menos un bit. [cita requerida]

La función de hash Keccak, que fue seleccionada por el NIST como el ganador del concurso SHA-3, no necesita este enfoque anidado y se puede utilizar para generar un MAC simplemente anteponiendo la clave del mensaje.[5]

Seguridad

[editar]

La fuerza criptográfica del HMAC depende del tamaño de la clave secreta que se utiliza. El ataque más común contra HMAC es la fuerza bruta para descubrir la clave secreta. HMAC está mucho menos afectada por las colisiones que sus algoritmos de hash subyacentes solos.[6][7][8]​ Por lo tanto, HMAC-MD5 no sufre de las mismas debilidades que se han encontrado en MD5.

En 2006, Jongsung Kim, Alex Biryukov, Bart Preneel y Seokhie Hong mostraron cómo distinguir HMAC con versiones reducidas de MD5 y SHA-1 o las versiones completas de HAVAL, MD4 y SHA-0 de una función aleatoria o HMAC con una función aleatoria. Diferentes distinciones permiten a un atacante idear un ataque de falsificación de HMAC. Además, diferentes y distinguidores rectangulares pueden conducir a ataques de segunda-preimagen. HMAC con la versión completa de MD4 se falsificó ese conocimiento. Estos ataques no contradicen la prueba de seguridad de HMAC, pero proporcionan información sobre HMAC basada en funciones hash criptográficas existentes.[9]

En 2009, Xiaoyun Wang presentó un ataque de identificación en HMAC-MD5 sin utilizar claves relacionadas. Se puede distinguir una instancia de HMAC con MD5 de una instancia con una función aleatoria con 2^97 consultas con probabilidad 0.87.[10]

En 2011 un informativo RFC 6151[11]​ se aprobó para actualizar las consideraciones de seguridad en MD5 y HMAC-MD5. Para HMAC-MD5 el RFC resume que -a pesar de la seguridad de la función hash MD5, ésta se ve gravemente comprometida- los actualmente conocidos "ataques contra HMAC-MD5 no parecen indicar una vulnerabilidad práctica cuando se utiliza como código de autentificación de mensajes."

En sistemas inadecuadamente-garantizados un ataque de tiempo se puede realizar para averiguar dígito a dígito de HMAC.[12]

Ejemplos de HMAC (MD5, SHA1, SHA256)

[editar]

Aquí hay algunos valores vacíos de HMAC:

HMAC_MD5("", "")    = 0x74e6f7298a9c2d168935f58c001bad88
HMAC_SHA1("", "")   = 0xfbdb1d1b18aa6c08324b7d64b71fb76370690e1d
HMAC_SHA256("", "") = 0xb613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad

Aquí hay algunos valores no vacíos HMAC, asumiendo 8-bit ASCII o UTF-8 codificación:

HMAC_MD5("key", "The quick brown fox jumps over the lazy dog")    = 0x80070713463e7749b90c2dc24911e275
HMAC_SHA1("key", "The quick brown fox jumps over the lazy dog")   = 0xde7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
HMAC_SHA256("key", "The quick brown fox jumps over the lazy dog") = 0xf7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

--

Referencias

[editar]
  1. a b Bellare, Mihir; Canetti, Ran; Krawczyk, Hugo (1996). «Keying Hash Functions for Message Authentication». 
  2. RFC 2104, section 2, "Definition of HMAC", page 3.
  3. hmac — Keyed-Hashing for Message Authentication, Python Software Foundation, consultado el 7 de mayo de 2014 .
  4. PHP: hash_hmac - Manual, The PHP Group, consultado el 13 de septiembre de 2015 .
  5. Keccak team. «Strengths of Keccak - Design and security». Consultado el 30 de enero de 2013. «Unlike SHA-1 and SHA-2, Keccak does not have the length-extension weakness, hence does not need the HMAC nested construction. Instead, MAC computation can be performed by simply prepending the message with the key.». 
  6. Bruce Schneier (August 2005). «SHA-1 Broken». Consultado el 9 de enero de 2009. «although it doesn't affect applications such as HMAC where collisions aren't important». 
  7. IETF (February 1997). «RFC 2104». Consultado el 3 de diciembre de 2009. «The strongest attack known against HMAC is based on the frequency of collisions for the hash function H ("birthday attack") [PV,BCK2], and is totally impractical for minimally reasonable hash functions.». 
  8. Bellare, Mihir (June 2006). «New Proofs for NMAC and HMAC: Security without Collision-Resistance». En Dwork, Cynthia, ed. Advances in Cryptology – Crypto 2006 Proceedings. Lecture Notes in Computer Science 4117. Springer-Verlag. Archivado desde el original|urlarchivo= requiere |url= (ayuda) el 16 de julio de 2011. Consultado el 25 de mayo de 2010. «This paper proves that HMAC is a PRF under the sole assumption that the compression function is a PRF. This recovers a proof based guarantee since no known attacks compromise the pseudorandomness of the compression function, and it also helps explain the resistance-to-attack that HMAC has shown even when implemented with hash functions whose (weak) collision resistance is compromised.». 
  9. Jongsung, Kim; Biryukov, Alex; Preneel, Bart; Hong, Seokhie (2006). On the Security of HMAC and NMAC Based on HAVAL, MD4, MD5, SHA-0 and SHA-1. Archivado desde el original el 12 de mayo de 2013. Consultado el 2 de noviembre de 2015. 
  10. Wang, Xiaoyun; Yu, Hongbo; Wang, Wei; Zhang, Haina; Zhan, Tao (2009). Cryptanalysis on HMAC/NMAC-MD5 and MD5-MAC. Consultado el 15 de junio de 2015. 
  11. «RFC 6151 – Updated Security Considerations for the MD5 Message-Digest and the HMAC-MD5 Algorithms». Internet Engineering Task Force. marzo de 2011. Consultado el 15 de junio de 2015. 
  12. Briefly mentioned at the end of this session Sebastian Schinzel:Time is on my Side - Exploiting Timing Side Channel Vulnerabilities on the Web 28th Chaos Communication Congress, 2011.
Notes
  • Mihir Bellare, Ran Canetti and Hugo Krawczyk, Keying Hash Functions for Message Authentication, CRYPTO 1996, pp1–15 (PS or PDF) Archivado el 9 de mayo de 2009 en Wayback Machine..
  • Mihir Bellare, Ran Canetti and Hugo Krawczyk, Message authentication using hash functions: The HMAC construction, CryptoBytes 2(1), Spring 1996 (PS or PDF) Archivado el 9 de mayo de 2009 en Wayback Machine..

Enlaces externos

[editar]