Generatore HMAC e verificatore di firme

Calcola HMAC-SHA-1, SHA-256, SHA-384 e SHA-512 da un messaggio e una chiave, e identifica da quale proviene una firma data.

Messaggio
HMAC-SHA-1
HMAC-SHA-256
HMAC-SHA-384
HMAC-SHA-512

Inserisci una chiave per calcolare le firme.

Che cosa fa questo strumento

HMAC trasforma un messaggio e un segreto condiviso in una firma breve. Chiunque possieda lo stesso segreto può ricalcolarla e vedere se il messaggio è arrivato immutato e se proviene da qualcuno che conosce anch’esso il segreto. Questo strumento calcola tutte e quattro le varianti comuni in una volta e, data una firma che ti è stata inviata, ti dice quale l’ha prodotta.

È di solito quel secondo verso il motivo per cui si arriva qui. Un webhook non supera la verifica, e la domanda vera non è «questa firma è valida» ma «quale delle diverse cose plausibili sto facendo diversamente dal mittente».

La chiave è dove le cose vanno storte

HMAC firma byte con byte. Il messaggio di solito è ovvio — il corpo grezzo della richiesta — ma la chiave quasi mai, perché un segreto arriva come stringa e una stringa non è byte finché non decidi come leggerla:

a3f2  ->  61 33 66 32   4 bytes   come testo
a3f2  ->  a3 f2         2 bytes   come hex

Entrambe le letture sono legittime, entrambe producono una firma perfettamente ben formata, e le due firme non hanno nulla in comune. Nulla ti avverte: nessun errore, nessuna lamentela sulla lunghezza, solo un valore che non coincide con quello calcolato dal mittente. Per questo qui la codifica della chiave è una scelta visibile e non un’ipotesi: quando una firma non coincide, è la prima cosa da ribaltare.

Come regola grossolana: un segreto con un prefisso tipo whsec_ o una sequenza di lettere maiuscole e minuscole e cifre di norma va inteso come testo; una stringa di esattamente 32 o 64 caratteri che usa solo 0-9 e a-f è di solito esadecimale; e una che finisce con = è quasi certamente Base64. Ma controlla la documentazione del mittente invece della forma, perché la forma non è una prova.

Il messaggio deve essere i byte esatti

L’altra metà di una mancata corrispondenza è il messaggio. HMAC è definito sui byte, quindi qualunque cosa cambi i byte cambia la firma per intero: non c’è punteggio parziale né quasi-centro.

  • Riserializzare il JSON. Analizzare un corpo e ricomporlo può riordinare le chiavi, cambiare gli spazi o normalizzare i numeri. Firma e verifica il corpo grezzo che hai ricevuto, mai una copia andata e tornata.
  • Un a capo finale. Alcuni strumenti lo aggiungono quando salvi il corpo su file; è un byte, e cambia tutto.
  • La codifica dei caratteri. Un corpo che contiene testo non ASCII va letto con la stessa codifica da entrambe le parti: in pratica UTF-8.
  • Compressione o middleware. Se qualcosa davanti al tuo handler decomprime o riscrive il corpo, verifica prima che accada, non dopo.

Molti provider inoltre non firmano il solo corpo. Stripe firma una marca temporale e il corpo uniti da un punto; AWS firma una richiesta canonica costruita da metodo, percorso, intestazioni e un hash del payload. Se la verifica fallisce contro il corpo semplice, la stringa firmata probabilmente non è il corpo semplice: è documentato dal lato del mittente e vale la pena leggerlo prima di continuare a indagare.

Perché SHA-1 è offerto qui e non nello strumento di hash

Lo strumento di hash segna SHA-1 come rotto. Questo elenca HMAC-SHA-1 senza avvisi, ed è deliberato, non una svista.

SHA-1 è inservibile per firme e certificati perché le collisioni si possono costruire: due documenti diversi si possono far condividere lo stesso digest. HMAC non dipende da quella proprietà. La sua sicurezza poggia sulla chiave segreta, e la costruzione — fare l’hash del messaggio due volte, con la chiave mescolata in entrambe — regge anche quando l’hash sottostante è debole alle collisioni. HMAC-SHA-1 resta solido ed è ciò che usano OAuth 1.0a e la vecchia firma AWS, perciò uno strumento che si rifiutasse di calcolarlo sarebbe semplicemente meno utile senza essere più sicuro.

Per qualcosa di nuovo, SHA-256 è la scelta sensata. Digest più lunghi non sono significativamente più forti qui — il tetto di sicurezza è la chiave, non la lunghezza del digest — quindi SHA-384 e SHA-512 valgono la pena solo quando qualcosa con cui devi interoperare li richiede.

Confrontare le firme in sicurezza

Questa pagina confronta con un normale confronto di stringhe, e qui va bene: la chiave ce l’hai tu, quindi non c’è nulla da far trapelare. In un server che verifica una richiesta in arrivo non va bene. Un confronto normale si ferma al primo byte diverso, quindi il tempo impiegato rivela quanta parte di un tentativo era corretta, e un attaccante che può inviare molte richieste può ricostruire una firma valida byte per byte.

Usa il confronto a tempo costante che la tua piattaforma offre — crypto.timingSafeEqual in Node, hmac.compare_digest in Python, hash_equals in PHP — sui byte grezzi e non su stringhe esadecimali. Insieme a questo: confronta con una firma che hai calcolato tu anziché fidarti di un algoritmo nominato nella richiesta, e rifiuta un messaggio la cui marca temporale è lontana da adesso, così una vecchia firma valida non può essere riutilizzata.

HMAC non è un hash né una firma

Qui si confondono tre cose, e la differenza conta per ciò che si può affermare dopo:

  • Un hash prende un messaggio e produce un digest. Chiunque può calcolarlo, quindi dimostra che il messaggio non è cambiato per sbaglio, non che venga da qualcuno in particolare.
  • Un HMAC prende un messaggio e un segreto condiviso. Entrambe le parti hanno la stessa chiave, quindi dimostra che il mittente conosceva il segreto. Non può dimostrare quale delle due abbia inviato, perché entrambe avrebbero potuto produrlo.
  • Una firma usa una chiave privata che solo il mittente possiede e una chiave pubblica con cui chiunque può verificare. È questo a dare il non ripudio: il mittente non può negarla in seguito.

HMAC è quindi lo strumento giusto fra due sistemi che già condividono un segreto — webhook, API interne, token di sessione — e quello sbagliato quando devi dimostrare a un terzo chi ha inviato qualcosa. Nota anche che autentica ma non nasconde: il messaggio viaggia in chiaro, e HMAC non dice nulla sulla riservatezza.

Domande frequenti

La mia firma non coincide. Che cosa controllo per primo?
La codifica della chiave, poi i byte del messaggio. Un segreto che sembra esadecimale spesso è inteso come esadecimale e non come testo, e i due producono firme completamente diverse senza alcun errore da nessuna delle due parti. Poi assicurati di firmare il corpo grezzo così come è arrivato e non una copia riserializzata.
Perché SHA-1 è offerto qui se lo strumento di hash lo dichiara rotto?
Perché HMAC non si basa sulla resistenza alle collisioni, la proprietà che SHA-1 ha perso. La sua sicurezza viene dalla chiave. HMAC-SHA-1 è ancora solido e in uso da OAuth 1.0a e dalla vecchia firma AWS, anche se SHA-256 è il valore predefinito giusto per qualcosa di nuovo.
Un digest più lungo è più sicuro?
Non in modo significativo. La forza di un HMAC è limitata dal segreto, non dalla lunghezza del digest, quindi SHA-512 non è quattro volte meglio di SHA-256. Scegli quello che si aspetta l’altra parte.
Che differenza c’è fra HMAC e una firma digitale?
HMAC usa un segreto che entrambe le parti conoscono, quindi dimostra che il mittente conosceva il segreto ma non quale parte abbia inviato. Una firma digitale usa una chiave privata che solo il mittente possiede, così un terzo può verificarla e il mittente non può negarla. Se ti serve quest’ultima proprietà, HMAC è lo strumento sbagliato.
Devo confrontare le firme con ===?
Non in un server. Un confronto normale ritorna appena i byte differiscono, e quel tempo rivela quanta parte di una firma indovinata era giusta. Usa il confronto a tempo costante della tua piattaforma sui byte grezzi. In questa pagina non ha importanza, perché la chiave ce l’hai già tu.
La mia chiave viene inviata da qualche parte?
No. Tutto viene calcolato nel tuo browser con la Web Crypto API; il messaggio e la chiave non lasciano mai il tuo dispositivo.