Gerador de HMAC

Calcule o HMAC de um texto, de bytes em hex ou de um arquivo com uma chave secreta, usando SHA-256, SHA-384, SHA-512, SHA-1 ou MD5, e compare-o com a assinatura de um webhook ou de uma API. Nada sai do seu navegador.

Funciona inteiramente no seu navegador. Nada é enviado.

Como usar

  1. Escolha o Algoritmo. HMAC-SHA256 vem selecionado por padrão e é o que a maioria dos webhooks e APIs usa.
  2. Informe a Chave secreta e defina o Formato da chave como Texto (lido como UTF-8), Hex ou Base64. Use Hex ou Base64 quando a chave for formada por bytes brutos, e não por uma string parecida com uma senha.
  3. Digite ou cole a Mensagem, mude a entrada para Hex para usar bytes brutos ou clique em Abrir arquivo. O HMAC é atualizado enquanto você digita.
  4. Em Saída como, escolha hex (minúsculas), HEX (maiúsculas) ou Base64 e copie o resultado, ou cole uma assinatura recebida em Comparar com para ver Confere ou Não confere.

Como o HMAC funciona

O HMAC (hash-based message authentication code, ou código de autenticação de mensagem baseado em hash, RFC 2104) combina um hash criptográfico com uma chave secreta. Só quem conhece a chave consegue produzir o valor correto para uma mensagem, então um HMAC que confere prova duas coisas ao mesmo tempo: a mensagem não foi alterada e veio de alguém que tem a chave.

A construção é H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)). Se a chave for maior que o tamanho de bloco do hash (64 bytes para MD5, SHA-1 e SHA-256; 128 para SHA-384 e SHA-512), ela primeiro passa pelo hash; depois é completada com zeros até esse tamanho e combinada por XOR com ipad (bytes 0x36), para um hash interno sobre a mensagem, e com opad (bytes 0x5c), para um hash externo sobre o resultado interno. Um SHA-256(key ‖ message) ingênuo não tem o hash externo, então quem vê uma única tag pode acrescentar dados à mensagem e calcular uma nova tag válida sem a chave (um ataque de extensão de comprimento).

A saída tem o comprimento do hash usado: 32 bytes, ou 64 caracteres hex, no HMAC-SHA256. A RFC 2104 recomenda uma chave pelo menos desse tamanho, e o gerador de Base64 aleatório cria chaves adequadas.

Onde as assinaturas HMAC são usadas

  • Webhooks do GitHub. O cabeçalho X-Hub-Signature-256 é sha256= seguido do HMAC-SHA256 em hex do corpo bruto da requisição, com o segredo do webhook como chave. Você pode colar o valor inteiro do cabeçalho em Comparar com; o prefixo sha256= é ignorado.
  • Webhooks da Stripe. O cabeçalho Stripe-Signature traz um timestamp t e uma assinatura v1: o HMAC-SHA256 em hex do timestamp, de um ponto e do corpo bruto, tendo como chave o segredo do endpoint (whsec_...) em formato de texto.
  • Webhooks da Shopify. X-Shopify-Hmac-Sha256 contém o HMAC-SHA256 do corpo bruto em Base64, com o segredo do cliente (client secret) do app como chave; então escolha a saída Base64 ou cole o valor do cabeçalho em Comparar com.
  • AWS Signature Version 4. A chave de assinatura é derivada encadeando HMAC-SHA256: a data, com AWS4 mais a chave de acesso secreta como chave; depois a região, o serviço e aws4_request, cada um com o resultado anterior como chave. Defina o Formato da chave como Hex para usar a saída de uma etapa na etapa seguinte.
  • JSON Web Tokens. HS256, HS384 e HS512 são HMAC-SHA256, -384 e -512 sobre o cabeçalho codificado, um ponto e o payload codificado. A terceira parte do token é esse HMAC em Base64 seguro para URL, que Comparar com aceita como está. O decodificador JWT verifica tokens inteiros.

Calcule sempre o HMAC sobre o corpo bruto, exatamente como ele foi recebido. Analisar o JSON e serializá-lo de novo muda os espaços ou a ordem das chaves, e até uma quebra de linha a mais gera um HMAC completamente diferente.

HMAC no código

# Python
import hmac, hashlib
sig = hmac.new(b'key', b'message', hashlib.sha256).hexdigest()
hmac.compare_digest(sig, received)        # comparação em tempo constante

// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', 'key').update('message').digest('hex');
// timingSafeEqual lança um erro se os comprimentos forem diferentes, então confira-os antes
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(received));

// PHP: a mensagem vem antes da chave
$sig = hash_hmac('sha256', 'message', 'key');
hash_equals($sig, $received);

# OpenSSL: uma chave em texto e depois a mesma chave em hex
printf '%s' 'message' | openssl dgst -sha256 -hmac 'key'
printf '%s' 'message' | openssl dgst -sha256 -mac HMAC -macopt hexkey:6b6579

# Vetor de teste: chave "key", mensagem "The quick brown fox jumps over the lazy dog"
# HMAC-SHA256 = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

Ao verificar uma assinatura no seu próprio código, use uma comparação em tempo constante como as mostradas acima. Um == simples para no primeiro caractere diferente, e essa diferença de tempo pode permitir que um atacante descubra uma assinatura válida byte a byte. Em esquemas com timestamp, como o da Stripe, rejeite também as requisições cujo timestamp tenha mais de alguns minutos, o que bloqueia ataques de replay.

Perguntas frequentes

O HMAC-MD5 ou o HMAC-SHA1 ainda são seguros?

Ataques de colisão quebram o MD5 e o SHA-1 como hashes simples, mas não oferecem uma forma prática de forjar um HMAC, que depende de outras propriedades do hash e de uma chave secreta (a RFC 6151 discute o HMAC-MD5). Integrações que os exigem, como os códigos TOTP baseados em HMAC-SHA1, podem continuar como estão. Em projetos novos, use HMAC-SHA256.

Por que meu HMAC não confere com a assinatura do webhook?

As causas mais comuns são calcular o hash do JSON analisado e serializado de novo em vez do corpo bruto, uma quebra de linha no fim da mensagem, o segredo ou o formato de chave errado (um segredo em Base64 ou hex informado como Texto, ou o contrário) e o algoritmo errado. Hex ou Base64 não é problema aqui: Comparar com aceita hex em maiúsculas ou minúsculas, Base64 padrão e Base64 seguro para URL.

Qual é a diferença entre HMAC e um hash simples?
Qualquer pessoa pode calcular um hash simples como o SHA-256, então ele só mostra que os dados não foram alterados por acidente. Um HMAC só pode ser calculado com a chave secreta, então um HMAC válido também mostra que ele foi gerado por alguém que tem essa chave.
Um HMAC é o mesmo que uma assinatura digital?

Não. Os dois lados de um HMAC compartilham o mesmo segredo, então quem consegue verificar uma tag também consegue criá-la. Assinaturas como RSA ou ECDSA (RS256 ou ES256 em JWTs) são feitas com uma chave privada e verificadas com uma chave pública, então quem as verifica não consegue forjá-las.

Minha chave secreta é enviada a um servidor?

Não. O HMAC-SHA1 e as variantes SHA-2 são calculados com a Web Crypto API do seu navegador, e o HMAC-MD5, por JavaScript na própria página. A chave e a mensagem nunca saem do seu dispositivo. Mesmo assim, trate segredos de produção com cuidado e faça a rotação de uma chave se ela puder ter sido exposta.