Utilia

Gerador de HMAC

Calcula um HMAC-SHA1, SHA-256, SHA-384 ou SHA-512 com chave em texto, hex ou Base64, obtém hex e Base64 e verifica a assinatura de um webhook.

A mensagem é assinada exatamente como foi escrita, codificada em UTF-8, incluindo espaços e quebras de linha.

A comparação é feita em tempo constante, como um servidor deve fazer, para que o tempo gasto não revele quantos caracteres coincidem.

Como calcular um HMAC

  1. Cola a Mensagem. Num webhook, tem de ser o corpo em bruto do pedido, byte a byte.
  2. Introduz a Chave secreta e escolhe o Formato da chave: Texto (UTF-8), Hexadecimal ou Base64.
  3. Escolhe o Algoritmo: HMAC-SHA1, HMAC-SHA256, HMAC-SHA384 ou HMAC-SHA512.
  4. O resultado atualiza-se enquanto escreves; também podes clicar em Gerar HMAC. Obténs o HMAC (hex), o HMAC (Base64) e um Cabeçalho de assinatura de webhook (estilo GitHub), cada um com um botão Copiar.
  5. Para verificar uma assinatura que recebeste, cola-a em Comparar com uma assinatura esperada (hex, Base64 ou sha256=…). A ferramenta diz-te se corresponde.

A mensagem é codificada em UTF-8 exatamente como foi escrita, incluindo espaços e quebras de linha. O cálculo usa a API Web Crypto do teu navegador; a mensagem e a chave nunca saem do teu dispositivo.

O que é um HMAC

Um HMAC (hash-based message authentication code, RFC 2104) combina uma chave secreta com uma função de hash:

HMAC(K, m) = H((K′ ⊕ opad) ‖ H((K′ ⊕ ipad) ‖ m))

em que K′ é a chave completada até ao tamanho do bloco do hash (e convertida primeiro em hash se for mais longa), e ipad/opad são constantes fixas. Só quem conhece a chave consegue produzir o código certo para uma mensagem, e qualquer alteração à mensagem muda o código por completo. É por isso que os HMAC assinam webhooks, pedidos de API (por exemplo, a AWS Signature Version 4) e os JSON Web Tokens HS256.

Um HMAC não é encriptação: a mensagem não fica escondida. Também não é um hash de palavras-passe; para guardar palavras-passe, usa uma função lenta como bcrypt ou Argon2.

O comprimento do resultado depende do algoritmo: 20 bytes para SHA-1, 32 para SHA-256, 48 para SHA-384 e 64 para SHA-512. O HMAC-SHA1 continua a ser considerado seguro como MAC, mas prefere o SHA-256 em sistemas novos. Recomenda-se uma chave aleatória pelo menos tão longa como o resultado (32 bytes para HMAC-SHA256); as chaves em hex ou Base64 permitem introduzir diretamente esses bytes aleatórios.

Verificar um webhook do GitHub

O GitHub assina cada entrega com o segredo do teu webhook e envia o resultado no cabeçalho X-Hub-Signature-256, como sha256= seguido do HMAC-SHA256 do corpo em hex. O exemplo da própria documentação do GitHub usa o segredo It's a Secret to Everybody e o corpo Hello, World!; introduz-os aqui com HMAC-SHA256 e o cabeçalho mostra:

X-Hub-Signature-256: sha256=757107ea0eb2509fc211221cce984b8a37570b6d7586c22c46f4379c8b043e17

O campo de comparação aceita a linha completa do cabeçalho, o valor sha256=… ou uma assinatura simples em hex ou Base64 (o Stripe, o Shopify e o Slack usam esquemas parecidos, com cabeçalhos e strings assinadas próprios). Para SHA-384 e SHA-512, a ferramenta mostra um cabeçalho genérico X-Signature, já que não existe um padrão comum.

Comparação em tempo constante

Um servidor que compara assinaturas com uma comparação de strings normal para no primeiro carácter diferente. Medindo os tempos de resposta, um atacante poderia adivinhar uma assinatura válida um carácter de cada vez. A comparação desta ferramenta examina todos os bytes, seja qual for o resultado, tal como um servidor deve fazer com crypto.timingSafeEqual em Node.js, hmac.compare_digest em Python ou hash_equals em PHP.

Perguntas frequentes

Porque é que o meu HMAC é diferente do calculado pelo meu servidor?

As causas habituais são uma mensagem diferente (o servidor assina o corpo em bruto e tu colaste JSON reformatado, ou as quebras de linha diferem), uma chave no Formato da chave errado ou outro algoritmo. Até um espaço a mais muda o resultado inteiro.

O resultado deve estar em hex ou em Base64?

Os dois codificam os mesmos bytes. O GitHub usa hex, enquanto muitas outras APIs, como a do Shopify, usam Base64. Usa o formato que o sistema recetor espera.

Posso usar uma chave vazia?

A ferramenta aceita-a e avisa-te: com uma chave vazia, qualquer pessoa consegue calcular o mesmo HMAC, por isso não prova nada.

O HMAC-SHA1 está quebrado como o SHA-1?

Os ataques de colisão ao SHA-1 não quebram o HMAC-SHA1, que continua a ser considerado seguro como MAC. Mantém-se suportado para sistemas antigos, como o antigo cabeçalho X-Hub-Signature, mas os sistemas novos devem usar HMAC-SHA256 ou mais forte.

A minha chave secreta está segura aqui?

A chave e a mensagem são processadas apenas no teu navegador e nunca são enviadas para lado nenhum. Ainda assim, trata com cuidado um segredo de produção e substitui-o se achares que foi exposto.