Generatore HMAC

Calcola l’HMAC di un testo, di byte esadecimali o di un file con una chiave segreta, usando SHA-256, SHA-384, SHA-512, SHA-1 o MD5, e confrontalo con la firma di un webhook o di un’API. Nessun dato lascia il tuo browser.

Funziona interamente nel tuo browser. Non viene caricato nulla.

Come si usa

  1. Scegli l’Algoritmo. HMAC-SHA256 è selezionato per impostazione predefinita ed è quello usato dalla maggior parte di webhook e API.
  2. Inserisci la Chiave segreta e imposta Formato della chiave su Testo (letto come UTF-8), Esadecimale o Base64. Usa Esadecimale o Base64 quando la chiave è composta da byte grezzi e non da una stringa simile a una password.
  3. Digita o incolla il Messaggio, imposta Formato input su Esadecimale per inserire byte grezzi oppure fai clic su Apri file. L’HMAC si aggiorna mentre scrivi.
  4. In Formato output scegli hex (minuscole), HEX (maiuscole) o Base64 e copia il risultato, oppure incolla una firma ricevuta in Confronta con per vedere Corrisponde o Non corrisponde.

Come funziona HMAC

HMAC (hash-based message authentication code, RFC 2104) combina una funzione di hash crittografica con una chiave segreta. Solo chi conosce la chiave può produrre il valore corretto per un messaggio, quindi un HMAC corrispondente dimostra due cose insieme: il messaggio non è stato modificato e proviene da qualcuno in possesso della chiave.

La costruzione è H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ message)). Se la chiave è più lunga della dimensione del blocco dell’hash (64 byte per MD5, SHA-1 e SHA-256, 128 per SHA-384 e SHA-512), viene prima sottoposta a hash; poi viene completata con zeri fino a quella dimensione e combinata in XOR con ipad (byte 0x36) per un hash interno calcolato sul messaggio, e con opad (byte 0x5c) per un hash esterno calcolato sul risultato interno. Una costruzione ingenua come SHA-256(key ‖ message) non ha un hash esterno, quindi chiunque veda un tag può aggiungere dati al messaggio e calcolare un nuovo tag valido senza conoscere la chiave (attacco di estensione della lunghezza, o length extension).

L’output ha la lunghezza dell’hash sottostante: 32 byte, ovvero 64 caratteri esadecimali, per HMAC-SHA256. La RFC 2104 raccomanda una chiave lunga almeno altrettanto, e il generatore Base64 casuale crea chiavi adatte.

Dove si usano le firme HMAC

  • Webhook di GitHub. L’header X-Hub-Signature-256 è formato da sha256= seguito dall’HMAC-SHA256 in esadecimale del corpo grezzo della richiesta, calcolato con il segreto del webhook come chiave. Puoi incollare l’intero valore dell’header in Confronta con: il prefisso sha256= viene ignorato.
  • Webhook di Stripe. L’header Stripe-Signature contiene un timestamp t e una firma v1: l’HMAC-SHA256 in esadecimale del timestamp, di un punto e del corpo grezzo, calcolato con il segreto dell’endpoint (whsec_...) usato come testo.
  • Webhook di Shopify. X-Shopify-Hmac-Sha256 contiene l’HMAC-SHA256 del corpo grezzo in Base64, calcolato con il client secret dell’app come chiave, quindi scegli l’output Base64 oppure incolla il valore dell’header in Confronta con.
  • AWS Signature Version 4. La chiave di firma si ottiene applicando HMAC-SHA256 a catena: prima alla data, con chiave AWS4 seguita dalla secret access key, poi alla regione, al servizio e a aws4_request, ogni volta con il risultato precedente come chiave. Imposta Formato della chiave su Esadecimale per usare l’output di un passaggio come chiave del successivo.
  • JSON Web Token. HS256, HS384 e HS512 sono HMAC-SHA256, -384 e -512 calcolati sull’header codificato, un punto e il payload codificato. La terza parte del token è proprio quell’HMAC in Base64 sicuro per URL, che Confronta con accetta così com’è. Il decodificatore JWT verifica token completi.

Calcola sempre l’HMAC sul corpo grezzo, esattamente come è stato ricevuto. Analizzare il JSON e serializzarlo di nuovo cambia gli spazi o l’ordine delle chiavi, e basta un solo a capo in più per ottenere un HMAC completamente diverso.

HMAC nel codice

# Python
import hmac, hashlib
sig = hmac.new(b'key', b'message', hashlib.sha256).hexdigest()
hmac.compare_digest(sig, received)        # confronto a tempo costante

// Node.js
const crypto = require('crypto');
const sig = crypto.createHmac('sha256', 'key').update('message').digest('hex');
// timingSafeEqual genera un errore se le lunghezze sono diverse, quindi controllale prima
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(received));

// PHP: il messaggio va prima della chiave
$sig = hash_hmac('sha256', 'message', 'key');
hash_equals($sig, $received);

# OpenSSL: una chiave di testo, poi la stessa chiave in esadecimale
printf '%s' 'message' | openssl dgst -sha256 -hmac 'key'
printf '%s' 'message' | openssl dgst -sha256 -mac HMAC -macopt hexkey:6b6579

# Vettore di test: chiave "key", messaggio "The quick brown fox jumps over the lazy dog"
# HMAC-SHA256 = f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8

Quando verifichi una firma nel tuo codice, usa un confronto a tempo costante come quelli qui sopra. Un semplice == si ferma al primo carattere diverso, e quella differenza nei tempi può permettere a un attaccante di trovare una firma valida byte per byte. Per gli schemi con timestamp, come quello di Stripe, rifiuta anche le richieste il cui timestamp risale a più di qualche minuto prima: in questo modo blocchi gli attacchi di replay.

Domande frequenti

HMAC-MD5 e HMAC-SHA1 sono ancora sicuri?

Gli attacchi di collisione compromettono MD5 e SHA-1 come semplici funzioni di hash, ma non offrono un modo pratico per falsificare un HMAC, che dipende da altre proprietà dell’hash e da una chiave segreta (la RFC 6151 analizza HMAC-MD5). Le integrazioni che li richiedono, come i codici TOTP basati su HMAC-SHA1, possono restare come sono. Per i nuovi progetti usa HMAC-SHA256.

Perché il mio HMAC non corrisponde alla firma del webhook?

Le cause più comuni sono: calcolare l’HMAC su un JSON analizzato e riserializzato invece che sul corpo grezzo, un a capo finale nel messaggio, un segreto o un formato della chiave sbagliato (un segreto Base64 o esadecimale inserito come Testo, o viceversa) e l’algoritmo sbagliato. Usare l’esadecimale o il Base64, invece, non è un problema: Confronta con accetta valori esadecimali in maiuscolo o minuscolo, Base64 standard e Base64 sicuro per URL.

Che differenza c’è tra un HMAC e un semplice hash?
Chiunque può calcolare un semplice hash come SHA-256, quindi questo dimostra solo che i dati non sono stati modificati per errore. Un HMAC si può calcolare solo con la chiave segreta, quindi un HMAC valido dimostra anche che è stato creato da qualcuno che possiede quella chiave.
Un HMAC è la stessa cosa di una firma digitale?

No. Con un HMAC entrambe le parti condividono lo stesso segreto, quindi chiunque possa verificare un tag può anche crearne uno. Le firme come RSA o ECDSA (RS256 o ES256 nei JWT) si creano con una chiave privata e si verificano con una chiave pubblica, quindi chi le verifica non può falsificarle.

La mia chiave segreta viene inviata a un server?

No. HMAC-SHA1 e le varianti SHA-2 vengono calcolati con la Web Crypto API del tuo browser, HMAC-MD5 con JavaScript direttamente nella pagina. La chiave e il messaggio non lasciano mai il tuo dispositivo. Tratta comunque con cura i segreti di produzione e sostituisci una chiave se potrebbe essere stata esposta.