Em criptografia, o código de autenticação de mensagem com chave hash (do inglês: keyed-hash message authentication code, abreviado HMAC) ou código de autenticação de mensagem com base em hash (do inglês: hash-based message authentication code) é um tipo específico de código de autenticação de mensagem (MAC) que usa uma função hash criptográfica e uma chave criptográfica secreta; que pode ser usado para verificar simultaneamente a integridade dos dados e a autenticidade de uma mensagem. Qualquer função hash criptográfica, como SHA-256 ou SHA-3, pode ser usada no cálculo de um HMAC; o algoritmo MAC resultante é denominado HMAC-X, em que X é a função de hash usada (por exemplo, HMAC-SHA256 ou HMAC-SHA3). A força criptográfica do HMAC depende da força criptográfica da função de hash subjacente, do tamanho de sua saída de hash e do tamanho e qualidade da chave.

Geração de um HMAC-SHA1

O HMAC usa duas passagens de computação de hash. A chave secreta é usada primeiro para derivar duas chaves - interna e externa. A primeira passagem do algoritmo produz um hash interno derivado da mensagem e da chave interna. A segunda passagem produz o código HMAC final derivado do resultado do hash interno e da chave externa. Assim, o algoritmo fornece melhor imunidade contra ataques de extensão de comprimento.

Uma função de hash iterativa divide uma mensagem em blocos de tamanho fixo e itera sobre eles com uma função de compactação. Por exemplo, o SHA-256 opera em blocos de 512 bits. O tamanho da saída do HMAC é o mesmo da função de hash subjacente (por exemplo, 256 e 1600 bits no caso de SHA-256 e SHA-3, respectivamente), embora possa ser truncado, se desejado.

O HMAC não criptografa a mensagem. Em vez disso, a mensagem (criptografada ou não) deve ser enviada juntamente com o hash HMAC. Os participantes com a chave secreta irão fazer o hash da mensagem novamente e, se for autêntico, os hashes recebidos e computados serão correspondentes.

A definição e análise da construção do HMAC foram publicadas pela primeira vez em 1996, em um artigo de Mihir Bellare, Ran Canetti e Hugo Krawczyk,[1] que também escreveram a RFC 2104 em 1997. O artigo de 1996 também definiu uma variante aninhada chamada NMAC. O FIPS PUB 198 generaliza e padroniza o uso de HMACs. O HMAC é usado nos protocolos IPsec e TLS; e para JSON Web Tokens.

Definição editar

Esta definição é proveniente da RFC 2104:

 

Em que:

  • H(·) é uma função hash criptográfica
  • K é uma chave secreta preenchida com zeros extras à direita para entrada no bloco do tamanho da função hash; ou o hash da chave original se esta é maior que o tamanho do bloco
  • m é a mensagem a ser autenticada
  • ∥ denota concatenação
  • ⊕ denota ou exclusivo (XOR)
  • opad é o preenchimento externo (0x5c5c5c…5c5c, um bloco de comprimento constante hexadecimal)
  • ipad é o preenchimento interno (0x363636…3636, um bloco de comprimento constante hexadecimal)

Implementação editar

O seguinte pseudocódigo demonstra como o HMAC pode ser implementado. O tamanho do bloco é 64 (bytes) quando uma das seguintes funções hash é usada: SHA-1, MD5, RIPEMD-160/128.[2]

function hmac (key, message)
    if (length(key) > blocksize) then
        key = hash(key) // encurta chaves maiores que o bloco (64 bytes)
    end if
    if (length(key) < blocksize) then
        key = key ∥ [0x00 * (blocksize - length(key))] // alonga chaves menores que o bloco ('∥' = concatenação) 
    end if
    o_key_pad = [0x5c * blocksize] ⊕ key // blocksize é o tamanho do bloco da função hash
    i_key_pad = [0x36 * blocksize] ⊕ key // '⊕' = operação “ou exclusivo” (XOR)
    return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) // '∥' = concatenação
end function

Abaixo, uma implementação Python do HMAC-MD5:

# !/usr/bin/env python
from hashlib import md5
trans_5C = "".join(chr(x ^ 0x5c) for x in xrange(256))
trans_36 = "".join(chr(x ^ 0x36) for x in xrange(256))
blocksize = md5().block_size

def hmac_md5(key, msg):
    if len(key) > blocksize:
        key = md5(key).digest()
    key += chr(0) * (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__":
    h = hmac_md5("key", "The quick brown fox jumps over the lazy dog")
    print h.hexdigest()  # 80070713463e7749b90c2dc24911e275

Exemplo de uso editar

Uma empresa que sofre com atacantes que inserem pedidos fraudulentos pela internet podem solicitar que todos os seus clientes forneçam uma chave secreta com eles. Junto com um pedido, um cliente deve fornecer o resumo do HMAC do pedido, computado por meio da chave simétrica do cliente. A empresa, que conhece a chave simétrica do cliente, pode então verificar que o pedido se originou a partir do cliente indicado e não foi adulterado.

Princípios de projeto editar

O projeto da especificação do HMAC foi motivado pela existência de ataques a mecanismos mais triviais por combinar uma chave com uma função hash. Por exemplo, pode-se supor que a mesma segurança que o HMAC provê poderia ser alcançada com MAC = H(chavemensagem). Contudo, este método apresenta uma falha grave: como a maioria das funções hash, é fácil acrescentar dados a mensagem sem conhecer a chave e obter outro MAC válido (“ataque extensão de comprimento”). A alternativa, anexando a chave usando MAC = H(mensagemchave), sofre com o problema de que um atacante que pode encontrar uma colisão em uma função hash (sem chave) tem uma colisão no MAC (como duas mensagens m1 e m2 produzem o mesmo hash será fornecido a mesma condição de início para a função hash antes que a chave adiciona seja hashed, portanto, o hash final será o mesmo). Usando MAC = H(chavemensagemchave) é melhor, contudo diversos papers sobre segurança apresentam vulnerabilidades com esta abordagem, mesmo quando duas chaves distintas são utilizadas.[1][3][4]

Nenhuma extensão de ataque tem sido encontrada contra a especificação atual do HMAC o qual é definido como H(chave1H(chave2mensagem)) porque a aplicação da função hash externa mascara o resultado intermediário do hash interno. Os valores do ipad e do opad não são críticos para a segurança do algoritmo, mas foram definidos de tal modo a ter uma grande distância de Hamming entre si e assim as chaves interna e externa terão menos bits em comum.

Segurança editar

A força criptográfica do HMAC depende do tamanho da chave secreta que é usada. O ataque mais comum contra HMACs é a força bruta para descobrir a chave secreta. HMACs são substancialmente menos afetados por colisões do que os seus algoritmos de hash subjacentes sendo utilizados sozinhos.[5][6][7] Portanto, HMAC-MD5 não sofre as mesmas fraquezas que foram encontradas no MD5.

Em 2006, Jongsung Kim, Alex Biryuukov, Bart Preneel e Seokhie Hong mostraram como distinguir HMAC com versões reduzidas de MD5 e SHA-1 ou versões completas do HAVAL, MD4, e SHA-0 de uma função aleatória ou HMAC com uma função aleatória. Distinguidores diferenciais permitem que um atacante planeje um ataque de falsificação no HMAC. Além disso, distinguidores diferenciais e distinguidores retangulares podem levar a um ataque de segunda pré-imagem. HMAC com versões completas do MD4 podem ser falsificados com este conhecimento. Estes ataques não contradizem a prova de segurança do HMAC, mas fornecem informações sobre o HMAC baseadas em funções hash criptográficas existentes.[8]

Pelo menos teoricamente, um ataque de temporização pode ser realizado para descobrir um HMAC dígito por dígito.[9]

Exemplo de HMAC (MD5, SHA1, SHA256) editar

Aqui estão alguns valores vazios HMAC -

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

Aqui estão alguns valores não vazios HMAC -

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

Nota: Os dados de entrada e a chave são do tipo ANSI de byte único, e não de dois bytes UCS-2 encoded Unicode Characters.

Referências

  1. a b Bellare, Mihir; Canetti, Ran; Krawczyk, Hugo (1996). «Keying Hash Functions for Message Authentication». CiteSeerx (em inglês). Consultado em 25 de novembro de 2022 [ligação inativa] 
  2. Krawczyk, Hugo; Bellare, Mihir; Canetti, Ran (fevereiro de 1997). «HMAC: Keyed-Hashing for Message Authentication». RFC Editor. Network Working Group (em inglês): 3. ISSN 2070-1721. RFC 2104 . doi:10.17487/RFC2104. Consultado em 25 de novembro de 2022 
  3. Preneel, Bart; C. Van Oorschot, Paul (1995). «MDx-MAC and Building Fast MACs from Hash Functions». CiteSeerx (em inglês). Consultado em 25 de novembro de 2022. Arquivado do original em 4 de junho de 2010 
  4. Preneel, Bart; C. Van Oorschot, Paul (1995). «On the Security of Two MAC Algorithms». CiteSeerx (em inglês). Consultado em 25 de novembro de 2022. Arquivado do original em 23 de fevereiro de 2009 
  5. Schneier, Bruce (agosto de 2005). «SHA-1 Broken». Schneier (em inglês). Consultado em 25 de novembro de 2022. although it doesn't affect applications such as HMAC where collisions aren't important 
  6. Bellare, Mihir; Canetti, Ran (fevereiro de 1997). «HMAC: Keyed-Hashing for Message». IETF (em inglês). Network Working Group. RFC 2104 . Consultado em 25 de novembro de 2022. 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. 
  7. Bellare, Mihir (2006). «New Proofs for NMAC and HMAC: Security without Collision-Resistance». In: Dwork, Cynthia. Advances in Cryptology – Crypto 2006 Proceedings. Lecture Notes in Computer Science 4117 (em inglês). Springer-Verlag. Consultado em 25 de novembro de 2022. 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. [ligação inativa] 
  8. 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» (PDF) (em inglês). Consultado em 25 de novembro de 2022 
  9. «28C3: Time is on my Side». FahrPlan (em inglês). 7 de janeiro de 2012. Consultado em 25 de novembro de 2022 

Bibliografia editar

  • Mihir Bellare, Ran Canetti and Hugo Krawczyk, Keying Hash Functions for Message Authentication, CRYPTO 1996, pp1–15 (PS or PDF).
  • Mihir Bellare, Ran Canetti and Hugo Krawczyk, Message authentication using hash functions: The HMAC construction, CryptoBytes 2(1), Spring 1996 (PS or PDF).

Ligações externas editar