<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Autenticazione on My personal blog</title>
        <link>https://www.matteobianchi.eu/tags/autenticazione/</link>
        <description>Recent content in Autenticazione on My personal blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Tue, 25 Aug 2026 09:00:00 +0200</lastBuildDate><atom:link href="https://www.matteobianchi.eu/tags/autenticazione/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>HMAC e autenticazione dei messaggi</title>
        <link>https://www.matteobianchi.eu/p/hmac-autenticazione-messaggi/</link>
        <pubDate>Tue, 25 Aug 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/hmac-autenticazione-messaggi/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/hmac-autenticazione-messaggi/cover.png" alt="Featured image of post HMAC e autenticazione dei messaggi" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;&lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/hashing-e-integrita/&#34; &gt;hash&lt;/a&gt; dimostra che i dati non sono cambiati, ma non
&lt;em&gt;chi&lt;/em&gt; li ha prodotti: un attaccante che controlla il canale cambia dati e hash insieme. Il &lt;strong&gt;MAC
(Message Authentication Code)&lt;/strong&gt; chiude il buco legando l&amp;rsquo;integrità a una &lt;strong&gt;chiave segreta&lt;/strong&gt;: solo chi
la possiede può generare un tag valido, e solo chi la possiede può verificarlo. È la stessa garanzia
di autenticità del tag AEAD, ma come primitiva a sé — usata ovunque ci siano token, webhook, API
firmate, cookie di sessione.&lt;/p&gt;
&lt;h2 id=&#34;hash-con-chiave-lidea-giusta-limplementazione-sbagliata&#34;&gt;Hash con chiave: l&amp;rsquo;idea giusta, l&amp;rsquo;implementazione sbagliata
&lt;/h2&gt;&lt;p&gt;L&amp;rsquo;intuizione è naturale: per autenticare, mescola la chiave segreta con il messaggio e fai l&amp;rsquo;hash.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Intuizione:  tag = H(chiave || messaggio)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# sembra ragionevole: solo chi ha la chiave produce il tag giusto...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# ...ma con gli hash della famiglia SHA-2 è VULNERABILE: length extension attack
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Il problema è un dettaglio della &lt;em&gt;costruzione&lt;/em&gt; di molti hash (Merkle–Damgård, come SHA-256): lo stato
interno è il digest stesso. Un attaccante che vede &lt;code&gt;H(chiave || messaggio)&lt;/code&gt; può &lt;strong&gt;estendere&lt;/strong&gt; il
messaggio — aggiungere dati in coda e calcolare un tag valido per &lt;code&gt;chiave || messaggio || extra&lt;/code&gt;
&lt;em&gt;senza conoscere la chiave&lt;/em&gt;. L&amp;rsquo;intuizione era giusta, la costruzione ingenua no.&lt;/p&gt;
&lt;h2 id=&#34;hmac-la-costruzione-corretta&#34;&gt;HMAC: la costruzione corretta
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;HMAC&lt;/strong&gt; risolve il length extension con una doppia applicazione dell&amp;rsquo;hash e due derivazioni della
chiave:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart LR
    K[Chiave] --&amp;gt; I[&amp;#34;ipad ⊕ K&amp;#34;]
    K --&amp;gt; O[&amp;#34;opad ⊕ K&amp;#34;]
    M[Messaggio] --&amp;gt; H1[&amp;#34;H(ipad⊕K ‖ M)&amp;#34;]
    I --&amp;gt; H1
    H1 --&amp;gt; H2[&amp;#34;H(opad⊕K ‖ hash interno)&amp;#34;]
    O --&amp;gt; H2
    H2 --&amp;gt; TAG[Tag HMAC]
    style H2 fill:#fde2e4,stroke:#e63946
&lt;/pre&gt;

&lt;p&gt;L&amp;rsquo;hash esterno &amp;ldquo;sigilla&amp;rdquo; quello interno, rendendo inefficace l&amp;rsquo;estensione. Il bello è che HMAC usa una
qualsiasi funzione di hash come componente: &lt;strong&gt;HMAC-SHA256&lt;/strong&gt; è lo standard di fatto. Non si implementa a
mano — ogni libreria crittografica lo offre pronto.&lt;/p&gt;
&lt;h2 id=&#34;il-confronto-deve-essere-a-tempo-costante&#34;&gt;Il confronto deve essere a tempo costante
&lt;/h2&gt;&lt;p&gt;Un errore sottile e frequente: verificare il tag con un confronto normale di stringhe.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# SBAGLIATO: &amp;#39;==&amp;#39; si ferma al primo byte diverso → il tempo rivela quanti byte combaciano&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tag_ricevuto&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tag_atteso&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# GIUSTO: confronto a tempo costante, indipendente da dove differiscono&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hmac&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;compare_digest&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;tag_ricevuto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;tag_atteso&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Un confronto che termina prima quando trova un byte diverso perde pochi microsecondi in meno: misurando
quei tempi, un attaccante ricostruisce il tag byte per byte (&lt;strong&gt;timing attack&lt;/strong&gt;). Le librerie offrono un
confronto &lt;em&gt;a tempo costante&lt;/em&gt; apposta: va usato sempre per dati segreti.&lt;/p&gt;
&lt;h2 id=&#34;mac-o-firma&#34;&gt;MAC o firma?
&lt;/h2&gt;&lt;p&gt;Il MAC è &lt;strong&gt;simmetrico&lt;/strong&gt;: la stessa chiave genera e verifica. Chi verifica può anche &lt;em&gt;forgiare&lt;/em&gt;. Va
benissimo quando le due parti si fidano e condividono il segreto (la tua app che firma i propri
token). Quando invece chi verifica &lt;em&gt;non&lt;/em&gt; deve poter generare — software distribuito al pubblico,
messaggi tra parti che non si fidano — serve l&amp;rsquo;asimmetria delle firme digitali, più avanti nella
serie.&lt;/p&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; se uso già AES-GCM, che è AEAD e autentica, perché dovrei conoscere l&#39;HMAC? Non è ridondante?&lt;/summary&gt;
&lt;p&gt;Non è ridondante perché risolvono lo stesso bisogno — autenticità e integrità — in contesti diversi, e
spesso te ne serve uno dove l&#39;altro non si applica. AES-GCM autentica &lt;em&gt;ciò che cifra&lt;/em&gt;: è la scelta
giusta quando devi insieme nascondere e proteggere dei dati. Ma moltissimi casi reali richiedono di
autenticare qualcosa che &lt;em&gt;non vuoi affatto cifrare&lt;/em&gt;, ed è lì che vive l&#39;HMAC. Pensa a un token di
sessione o a un JWT firmato: il payload spesso è leggibile di proposito (il client deve sapere chi è,
quando scade), ti serve solo garantire che nessuno lo abbia alterato — HMAC sul contenuto, nessuna
cifratura. Pensa ai webhook: un servizio esterno ti invia un evento in chiaro e allega un tag
HMAC-SHA256 calcolato con un segreto condiviso, così tu verifichi che l&#39;evento venga davvero da lui e non
sia stato manomesso in transito; cifrarlo non avrebbe senso, deve poterlo leggere chi lo riceve. Pensa
alla firma delle richieste API (lo stile AWS SigV4): firmi gli header e il corpo con HMAC per provare
l&#39;autenticità della chiamata, ma il contenuto resta quello che è. In tutti questi casi vuoi
&lt;em&gt;autenticità senza riservatezza&lt;/em&gt;, e tirare dentro una cifratura AEAD solo per ottenere il tag
sarebbe goffo e spesso controproducente. C&#39;è poi la questione del livello di astrazione: AES-GCM è un
AEAD che ti dà il tag come sottoprodotto del cifrare, mentre HMAC è la primitiva di autenticazione pura,
quella che usi anche come mattone dentro costruzioni più grandi — la derivazione di chiavi (HKDF è
costruito su HMAC), i meccanismi di challenge-response, la verifica di integrità di dati già cifrati con
altro. In breve: se devi cifrare, usa un AEAD e hai l&#39;autenticazione inclusa; se devi autenticare dati
che restano in chiaro — token, webhook, richieste, messaggi tra parti che condividono un segreto — HMAC è
lo strumento diretto e corretto. Conoscerli entrambi ti fa scegliere quello giusto invece di piegare
l&#39;uno al compito dell&#39;altro.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Il MAC lega integrità e autenticità a una chiave segreta; HMAC è la costruzione corretta che evita il
length extension, con HMAC-SHA256 come standard, e va verificato con un confronto a tempo costante. Ma
il MAC è simmetrico: chi verifica può forgiare. Un caso particolare di &amp;ldquo;hash con chiave&amp;rdquo; merita un
capitolo a sé, perché quasi tutti lo sbagliano — proteggere le password, prossimo capitolo.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
