Tutti gli articoli

HMAC: in cosa differisce un hash con chiave da un hash normale

PagoPA, la piattaforma nazionale italiana per i pagamenti verso la pubblica amministrazione, e diversi gateway privati come Nexi firmano le notifiche webhook con HMAC-SHA256: l'esercente riceve una chiave segreta in fase di configurazione, e ogni notifica in arrivo porta una firma che va ricalcolata localmente e confrontata con quella ricevuta. Se la firma non corrisponde, la notifica non proviene realmente dal fornitore di pagamento e non va trattata come una conferma di pagamento autentica.

Perché serve una chiave segreta, non solo un hash

Un hash normale come SHA-256 dimostra solo che i dati non sono stati alterati in transito, non chi li ha inviati. Se un server si limitasse a fare l'hash del corpo del webhook e confrontarlo con un hash incluso nella richiesta, un attaccante potrebbe fabbricare un proprio payload falso e allegare un hash corrispondente. HMAC risolve il problema mescolando una chiave segreta nota solo a mittente e destinatario: senza di essa, produrre una firma valida è impraticabile anche se l'attaccante conosce esattamente quale funzione hash viene usata.

Perché non è solo "hash della chiave più il messaggio"

Concatenare ingenuamente chiave e messaggio prima dell'hashing (per esempio hash(chiave + messaggio)) è vulnerabile ad attacchi di estensione della lunghezza per alcune funzioni hash — un attaccante può a volte aggiungere dati e calcolare un nuovo hash valido senza conoscere l'intera chiave. HMAC usa una costruzione specifica con doppio hashing e padding interno/esterno che chiude completamente questa classe di attacchi.

Dove compare ancora HMAC

Oltre alla firma dei webhook, HMAC autentica le richieste API ed è il nucleo dell'algoritmo TOTP, quello che genera i codici a sei cifre nelle app di autenticazione.

A cosa serve

  • Verificare l'autenticità dei webhook provenienti da gateway di pagamento o altri servizi terzi.
  • Firmare richieste API senza mai inviare la chiave segreta stessa sulla rete.
  • Capire il funzionamento interno dei codici TOTP e dei token di sessione.

Confronto a tempo costante

Confrontare una firma ricevuta con quella attesa usando un normale === è pericoloso: tale operatore di solito si ferma al primo byte di differenza, e il tempo di esecuzione del confronto rivela all'attaccante quanti dei primi byte ha indovinato correttamente. Un gestore di webhook implementato correttamente usa sempre una funzione di confronto a tempo costante — come hash_equals in PHP o crypto.timingSafeEqual in Node.js — che verifica sempre tutti i byte indipendentemente da dove si trova la prima differenza.

Prova lo strumento