HMAC Explicado
HMAC (Hash-Based Message Authentication Code) é um mecanismo para verificar tanto a integridade quanto a autenticidade de uma mensagem usando uma função hash criptográfica combinada com uma chave secreta. Ao contrário do hashing simples, que qualquer um pode calcular, o HMAC requer conhecimento da chave secreta para gerar ou verificar o código de autenticação.
Um hash simples como SHA256 diz-lhe que uma mensagem não foi alterada, mas não prova quem a criou. Um atacante que modifica a mensagem pode simplesmente recalcular o hash, e o destinatário não tem forma de detetar a adulteração. O HMAC resolve isto incorporando uma chave secreta no cálculo do hash. Apenas alguém com a chave pode produzir um HMAC válido, tornando-o adequado para autenticar mensagens entre partes que partilham um segredo.
Como o HMAC Funciona
O HMAC usa duas passagens da função hash com a chave secreta. O algoritmo é definido na RFC 2104 e funciona da seguinte forma:
- A chave secreta é preenchida até ao tamanho do bloco da função hash
- A chave preenchida é combinada com XOR com uma constante de preenchimento interno (ipad = 0x36 repetido)
- A mensagem é anexada à chave com preenchimento interno
- O resultado é hashado
- A chave preenchida é combinada com XOR com uma constante de preenchimento externo (opad = 0x5C repetido)
- O hash do passo 4 é anexado à chave com preenchimento externo
- O resultado é hashado novamente
HMAC(K, m) = H((K' ⊕ opad) || H((K' ⊕ ipad) || m))
Esta abordagem de hash duplo previne ataques de extensão de comprimento e garante que mesmo que a função hash subjacente tenha fraquezas, a construção HMAC permanece segura.
HMAC vs Hashing Simples
| Característica | Hash Simples (SHA256) | HMAC-SHA256 |
|---|---|---|
| Chave necessária | Não | Sim |
| Verificação de integridade | Sim | Sim |
| Autenticação | Não | Sim |
| Deteção de adulteração | Recalculo completo | Deteção sem chave |
| Melhor para | Checksums de ficheiros | Autenticação de API |
| Extensão de comprimento | Vulnerável | Resistente |
Casos de Uso Comuns
Autenticação de API — o cliente assina cada pedido com HMAC usando uma chave secreta partilhada. O servidor recalcula o HMAC e compara. Se coincidirem, o pedido é autêntico.
Assinatura de tokens JWT — embora o JWT normalmente use HMAC ou RSA mais simples, o HMAC é um algoritmo válido para JWT (HS256, HS384, HS512).
Verificação de webhooks — serviços como Stripe, GitHub e Slack assinam payloads de webhook com HMAC para que possa verificar que vieram do serviço.
Tokens de sessão — HMAC pode gerar tokens de sessão infalsificáveis sem armazená-los numa base de dados.
Exemplos de Código
PHP
$secret = 'my-secret-key';
$message = 'message-to-authenticate';
// Gerar HMAC
$hmac = hash_hmac('sha256', $message, $secret);
echo $hmac;
// Verificar HMAC
$expected = hash_hmac('sha256', $message, $secret);
if (hash_equals($expected, $providedHmac)) {
echo 'Authentic';
}
Python
import hmac
import hashlib
secret = b'my-secret-key'
message = b'message-to-authenticate'
# Gerar HMAC
hmac_value = hmac.new(secret, message, hashlib.sha256).hexdigest()
print(hmac_value)
# Verificar HMAC (comparação em tempo constante)
expected = hmac.new(secret, message, hashlib.sha256).digest()
received = bytes.fromhex(provided_hmac)
if hmac.compare_digest(expected, received):
print('Authentic')
JavaScript (Node.js)
const crypto = require('crypto');
const secret = 'my-secret-key';
const message = 'message-to-authenticate';
// Gerar HMAC
const hmac = crypto.createHmac('sha256', secret)
.update(message)
.digest('hex');
console.log(hmac);
// Verificar
const expected = crypto.createHmac('sha256', secret)
.update(message)
.digest();
Algoritmos HMAC
HMAC pode usar qualquer função hash criptográfica. O nome do algoritmo tipicamente combina "HMAC" com o nome do hash.
| Algoritmo | Função Hash | Tamanho de Saída |
|---|---|---|
| HMAC-MD5 | MD5 | 128 bits |
| HMAC-SHA1 | SHA-1 | 160 bits |
| HMAC-SHA256 | SHA-256 | 256 bits |
| HMAC-SHA512 | SHA-512 | 512 bits |
| HMAC-SHA3-256 | SHA3-256 | 256 bits |
Use HMAC-SHA256 como padrão. HMAC-MD5 e HMAC-SHA1 estão obsoletos para aplicações sensíveis à segurança.
Considerações de Segurança
Tamanho da chave — a chave deve ter pelo menos o tamanho da saída do hash. Para HMAC-SHA256, use uma chave de pelo menos 32 bytes (256 bits). Chaves mais longas são reduzidas por hash ao tamanho do bloco.
Sigilo da chave — a segurança do HMAC depende inteiramente de a chave ser secreta. Use um sistema de gestão de chaves ou variáveis de ambiente. Nunca codifique chaves no código fonte.
Comparação em tempo constante — compare sempre valores HMAC usando uma função de comparação em tempo constante como hash_equals() no PHP ou hmac.compare_digest() no Python. Um ataque de temporização poderia revelar o HMAC correto byte a byte.
Ataques de repetição — HMAC sozinho não previne ataques de repetição. Inclua um timestamp ou nonce na mensagem assinada e verifique-o no servidor.
Ferramenta Online
O HMAC Generator no Help2Code calcula valores HMAC com a sua escolha de algoritmo e chave secreta. Use-o para testar implementações HMAC ou gerar vetores de teste durante o desenvolvimento.
Conclusão
HMAC fornece autenticação de mensagens usando uma chave secreta partilhada e uma função hash criptográfica. É essencial para segurança de API, verificação de webhooks e qualquer cenário onde precise verificar tanto a integridade quanto a autenticidade de uma mensagem. Use HMAC-SHA256 com uma chave secreta forte e compare sempre valores HMAC usando funções de tempo constante.