<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Argon2 on My personal blog</title>
        <link>https://www.matteobianchi.eu/tags/argon2/</link>
        <description>Recent content in Argon2 on My personal blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Tue, 01 Sep 2026 09:00:00 +0200</lastBuildDate><atom:link href="https://www.matteobianchi.eu/tags/argon2/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Password hashing: lentezza come virtù</title>
        <link>https://www.matteobianchi.eu/p/password-hashing-argon2/</link>
        <pubDate>Tue, 01 Sep 2026 09:00:00 +0200</pubDate>
        
        <guid>https://www.matteobianchi.eu/p/password-hashing-argon2/</guid>
        <description>&lt;img src="https://www.matteobianchi.eu/p/password-hashing-argon2/cover.png" alt="Featured image of post Password hashing: lentezza come virtù" /&gt;&lt;h2 id=&#34;perché-conta&#34;&gt;Perché conta
&lt;/h2&gt;&lt;p&gt;Abbiamo visto che un &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/hashing-e-integrita/&#34; &gt;hash crittografico&lt;/a&gt; è progettato per
essere &lt;em&gt;veloce&lt;/em&gt;. Per le password questa è la proprietà sbagliata: la velocità lavora per l&amp;rsquo;attaccante.
Salvare le password è il caso d&amp;rsquo;uso che quasi tutti sbagliano, e lo sbaglio non si vede finché un
database non trapela — allora si scopre in un pomeriggio se erano protette davvero o solo in
apparenza. Le password richiedono un approccio opposto a tutto il resto della crittografia: la
lentezza come virtù.&lt;/p&gt;
&lt;h2 id=&#34;cosa-non-fare&#34;&gt;Cosa NON fare
&lt;/h2&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;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;4
&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;Password in chiaro          → ovvio disastro
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Cifrate (reversibili)       → la chiave è lì vicino; un furto le espone tutte
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SHA-256(password)           → miliardi di tentativi/secondo: dizionario esaurito in minuti
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SHA-256(password) senza salt → due utenti con la stessa password hanno lo stesso hash
&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 punto chiave: quando un database di hash trapela, l&amp;rsquo;attaccante non &amp;ldquo;decifra&amp;rdquo; — &lt;em&gt;indovina&lt;/em&gt;. Prova
miliardi di candidati (password comuni, dizionari, brute force) e confronta gli hash. Il suo limite è
la &lt;em&gt;velocità&lt;/em&gt;. Un hash veloce come SHA-256 gli regala miliardi di tentativi al secondo.&lt;/p&gt;
&lt;h2 id=&#34;salt-contro-il-precalcolo&#34;&gt;Salt: contro il precalcolo
&lt;/h2&gt;&lt;p&gt;Un &lt;strong&gt;salt&lt;/strong&gt; è un valore casuale, unico per ogni password, memorizzato accanto all&amp;rsquo;hash (non è
segreto). Si hasha &lt;code&gt;salt + password&lt;/code&gt;. Due effetti:&lt;/p&gt;
&lt;pre class=&#34;mermaid&#34;&gt;
  flowchart TD
    A[Senza salt] --&amp;gt; A1[Stessa password&amp;lt;br/&amp;gt;→ stesso hash] --&amp;gt; A2[Rainbow table:&amp;lt;br/&amp;gt;hash precalcolati&amp;lt;br/&amp;gt;riutilizzabili su tutti]
    B[Con salt unico] --&amp;gt; B1[Stessa password&amp;lt;br/&amp;gt;→ hash DIVERSI] --&amp;gt; B2[Precalcolo inutile:&amp;lt;br/&amp;gt;ogni hash va attaccato&amp;lt;br/&amp;gt;singolarmente]
    style A2 fill:#fde2e4,stroke:#e63946
    style B2 fill:#e8f0fe,stroke:#4361ee
&lt;/pre&gt;

&lt;p&gt;Il salt rende inutili le &lt;strong&gt;rainbow table&lt;/strong&gt; (tabelle di hash precalcolati) e impedisce di vedere quali
utenti condividono la stessa password. Ma non rallenta i tentativi: per quello serve altro.&lt;/p&gt;
&lt;h2 id=&#34;il-costo-regolabile&#34;&gt;Il costo regolabile
&lt;/h2&gt;&lt;p&gt;Gli algoritmi di password hashing sono &lt;em&gt;deliberatamente lenti e costosi&lt;/em&gt;, con un parametro di &lt;strong&gt;costo&lt;/strong&gt;
che puoi alzare man mano che l&amp;rsquo;hardware migliora:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bcrypt&lt;/strong&gt;: lento, con un fattore di costo (work factor). Collaudato da decenni.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;scrypt&lt;/strong&gt;: lento &lt;em&gt;e&lt;/em&gt; avido di &lt;strong&gt;memoria&lt;/strong&gt; (memory-hard), per neutralizzare le GPU.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Argon2&lt;/strong&gt;: vincitore della Password Hashing Competition, regolabile su tempo, memoria e
parallelismo. La variante &lt;strong&gt;Argon2id&lt;/strong&gt; è la raccomandazione di oggi.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;L&amp;rsquo;idea della &lt;em&gt;memory-hardness&lt;/em&gt; è cruciale: le GPU e gli ASIC hanno tantissimi core ma poca memoria per
core. Un algoritmo che richiede, diciamo, 64 MB per ogni tentativo annulla il vantaggio dell&amp;rsquo;hardware
parallelo, che è l&amp;rsquo;arma principale dell&amp;rsquo;attaccante.&lt;/p&gt;
&lt;h2 id=&#34;tararlo-bene&#34;&gt;Tararlo bene
&lt;/h2&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;/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;Obiettivo: un singolo hash impiega ~0,1–0,5s e usa decine di MB di RAM
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → per te (un login) è impercettibile
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  → per l&amp;#39;attaccante (miliardi di tentativi) è proibitivo in tempo E in costo hardware
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Rivaluta i parametri periodicamente: l&amp;#39;hardware migliora, il costo va alzato.
&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 parametro va scelto in base alla &lt;em&gt;tua&lt;/em&gt; infrastruttura: abbastanza alto da far male all&amp;rsquo;attaccante,
abbastanza basso da non rendere lento il login legittimo né esporti a un DoS. E va rivisto nel tempo.&lt;/p&gt;
&lt;h2 id=&#34;il-quadro-completo&#34;&gt;Il quadro completo
&lt;/h2&gt;&lt;p&gt;Password hashing robusto = &lt;strong&gt;Argon2id&lt;/strong&gt; (o bcrypt se Argon2 non è disponibile) + &lt;strong&gt;salt unico&lt;/strong&gt; per
utente (gestito automaticamente dalla libreria) + &lt;strong&gt;costo tarato&lt;/strong&gt; e rivisto. E, a monte, ridurre il
valore del bersaglio: MFA, &lt;a class=&#34;link&#34; href=&#34;https://www.matteobianchi.eu/p/gestione-dei-segreti/&#34; &gt;segreti gestiti bene&lt;/a&gt;, e dove
possibile passare a meccanismi senza password. Un database con password Argon2id ben tarate, se
trapela, costa all&amp;rsquo;attaccante molto più di quanto valgano la maggior parte degli account.&lt;/p&gt;


&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Domanda:&lt;/strong&gt; se il salt è memorizzato in chiaro accanto all&#39;hash, a cosa serve? L&#39;attaccante che ruba il database ha anche i salt.&lt;/summary&gt;
&lt;p&gt;È vero che l&#39;attaccante ottiene i salt insieme agli hash, e questo confonde molti — ma il salt non è
mai stato pensato per essere segreto, e capire a cosa serve davvero chiarisce perché funziona anche se è
pubblico. Il salt difende da un attacco specifico: il &lt;em&gt;precalcolo&lt;/em&gt; e la &lt;em&gt;condivisione del lavoro
tra più password&lt;/em&gt;. Senza salt, un attaccante può fare il lavoro una volta sola e riusarlo contro
tutti: costruisce in anticipo una gigantesca tabella (rainbow table) che mappa password comuni ai loro
hash, e poi, quando ruba un database, confronta semplicemente gli hash rubati con la tabella già pronta —
nessun calcolo nuovo, risposta immediata per milioni di account. Peggio, se due utenti hanno la stessa
password hanno lo stesso hash, quindi crackarne uno li crackа tutti insieme, e vedi subito chi condivide
la password. Il salt unico per utente distrugge entrambe le scorciatoie. Poiché ogni password è hashata
con un salt diverso, la tabella precalcolata diventa inutile: dovrebbe esistere una rainbow table separata
&lt;em&gt;per ogni salt possibile&lt;/em&gt;, cioè miliardi di tabelle, il che è infattibile — il precalcolo
collassa. E due utenti con la stessa password ora hanno hash diversi, quindi l&#39;attaccante deve attaccare
ogni account &lt;em&gt;singolarmente&lt;/em&gt;, da zero, senza riusare nulla. Nota bene cosa il salt fa e cosa non
fa: non rallenta il tentativo del &lt;em&gt;singolo&lt;/em&gt; hash — quello è compito del costo regolabile di
Argon2/bcrypt — ma impedisce all&#39;attaccante di ammortizzare lo sforzo su molte password o di pre-pagarlo
prima del furto. Il fatto che sia pubblico non lo indebolisce, perché la sua forza non sta nella
segretezza ma nell&#39;essere &lt;em&gt;unico e diverso per ciascuno&lt;/em&gt;: costringe l&#39;avversario a fare lavoro
fresco e separato per ogni password, invece di un lavoro solo riutilizzabile per tutte. Salt e costo
lavorano su assi ortogonali — il salt elimina le scorciatoie orizzontali (tra password), il costo rende
caro ogni singolo tentativo verticale — ed è la combinazione dei due a rendere un database rubato poco
redditizio da attaccare.&lt;/p&gt;
&lt;/details&gt;


&lt;h2 id=&#34;conclusione&#34;&gt;Conclusione
&lt;/h2&gt;&lt;p&gt;Le password si proteggono con algoritmi lenti e memory-hard — Argon2id oggi — con salt unico per
utente e costo tarato e rivisto nel tempo: mai in chiaro, mai cifrate, mai con un hash veloce.
Finora tutta la serie ha usato &lt;em&gt;chiavi condivise&lt;/em&gt;: la stessa chiave per cifrare e decifrare, per
generare e verificare. Ma come fanno due parti che non si sono mai incontrate a condividere una chiave?
È il problema che la crittografia asimmetrica risolve, prossimo capitolo.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
