Como calcular um HMAC em Base64
- O modo HMAC e o SHA-256 já vêm selecionados. Escolha outro em Algoritmo se a sua API usa SHA-1, SHA-384, SHA-512 ou MD5.
- Informe a Chave secreta e ajuste A chave está em: Texto (UTF-8) para uma string secreta comum, Hex ou Base64 se a chave vier como bytes codificados.
- Digite ou cole a mensagem em Texto, ou troque Entrada para Arquivo e arraste o arquivo com o payload exato.
- Copie a assinatura em Base64, Base64URL ou hex. Todos os algoritmos mostra o HMAC com todos os hashes de uma vez, o que ajuda quando a documentação não deixa claro qual é usado.
Uma chave vazia é aceita e ainda gera resultado, com um aviso de que esse HMAC não protege nada.
Valores de exemplo
Com a chave key e a mensagem The quick brown fox jumps over the lazy dog:
| Algoritmo | HMAC em Base64 |
|---|---|
| HMAC-MD5 | gAcHE0Y+d0m5DC3CSRHidQ== |
| HMAC-SHA1 | 3nybhbi3iqa8ino29wqQcBydtNk= |
| HMAC-SHA256 | 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg= |
| HMAC-SHA512 | tCrwkFe6weLUFwjkipAuCbX/fxKrQopP6GZTxz3SSPuC+UilSfe3kaW0GRXuTR7Dk1NX5OIxclDQNyr6Lr7rOg== |
O valor HMAC-SHA256 em hex é f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8, o vetor de teste conhecido do artigo da Wikipédia sobre HMAC. A codificação da chave muda tudo: o texto a2V5 usado como chave gera 5O+7AtpguFrgIRw1qXGU+m0OaTs1oV1kwRQ/hI1WAUE=, enquanto a2V5 lido como Base64 são os bytes de key e gera 97yD9DBT… de novo.
Assinaturas de webhook: Base64 ou hex
Os provedores concordam no HMAC, mas não na codificação da saída nem no que é assinado. Alguns exemplos bem documentados:
| Provedor | Header | Algoritmo | Codificação | Conteúdo assinado |
|---|---|---|---|---|
| Shopify | X-Shopify-Hmac-Sha256 | HMAC-SHA256 | Base64 | corpo bruto da requisição |
| Standard Webhooks (Svix) | webhook-signature: v1,… | HMAC-SHA256 | Base64 | id.timestamp.body, chave do whsec_ em Base64 |
| Twilio | X-Twilio-Signature | HMAC-SHA1 | Base64 | URL mais os parâmetros POST ordenados |
| GitHub | X-Hub-Signature-256: sha256=… | HMAC-SHA256 | hex | corpo bruto da requisição |
| Stripe | Stripe-Signature: t=…,v1=… | HMAC-SHA256 | hex | timestamp.body |
Quando um valor desta ferramenta bate com o hex mas o seu código compara Base64, ou o contrário, o cálculo está certo e só a codificação difere. Veja na documentação do provedor o que é assinado; os prefixos de timestamp existem para impedir a repetição de requisições antigas.
Verificar uma assinatura no código
Compare bytes brutos em tempo constante e garanta que o hash seja do corpo exatamente como foi recebido:
const crypto = require("crypto");
function verifyWebhook(rawBody, secret, signatureHeader) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest();
const given = Buffer.from(signatureHeader, "base64");
return given.length === expected.length && crypto.timingSafeEqual(given, expected);
}
Com rawBody sendo o Buffer da frase da raposa, o segredo key e o valor Base64 da tabela, a função devolve true. Passe JSON.stringify(JSON.parse(body)) no lugar do corpo bruto e ela devolve false assim que o JSON do provedor tiver um espaço que o seu serializador remove. No Express, isso significa ler o corpo com express.raw() na rota do webhook.
O equivalente em Python usa hmac.new(key, body, hashlib.sha256).digest(), codifica em Base64 e confere com hmac.compare_digest. Na linha de comando, openssl dgst -sha256 -hmac 'key' -binary | base64 dá o mesmo Base64; use -mac HMAC -macopt hexkey:… quando a chave estiver em hex. Para uma chave forte, o preset de segredo HMAC do gerador de chaves Base64 cria 32 bytes aleatórios. Para assinar tokens em vez de requisições, veja o codificador de JWT.
Perguntas frequentes
Por que o HMAC do meu webhook não bate?
A assinatura cobre os bytes exatos do corpo da requisição. Se o seu framework fez o parse do JSON e você calcula o hash de uma cópia reserializada, o espaçamento ou a ordem das chaves muda e o resultado é outro. Calcule sobre o corpo bruto, veja se o provedor espera hex ou Base64 e se o segredo precisa ser decodificado antes.
O segredo do HMAC é texto ou Base64?
Depende do provedor. A maioria entrega uma string que é usada como texto UTF-8. Alguns fornecem uma chave codificada em Base64, às vezes depois de um prefixo como whsec_, que precisa ser decodificada para bytes antes do uso. Ajuste A chave está em de acordo.
Qual a diferença entre hash e HMAC?
Qualquer pessoa calcula o SHA-256 de uma mensagem, então um hash só detecta alterações acidentais. Um HMAC mistura uma chave secreta, e só quem tem a chave consegue produzir um valor válido, o que faz dele uma assinatura.
Posso usar HMAC-MD5 ou HMAC-SHA1?
Os dois ainda são usados por APIs antigas e continuam bem mais fortes que MD5 ou SHA-1 puros, porque colisões não se traduzem em falsificação de HMAC. Para projetos novos, escolha HMAC-SHA256.