Ogni volta che un utente crea una password su un sito web, quella stringa passa attraverso un algoritmo di hashing prima di finire su un database. Nel 2026 la scelta tra bcrypt, Argon2id e scrypt non è più un dettaglio da manuale universitario: determina quanto costerà a un attaccante forzare quella password se il database viene rubato. La differenza tra i tre algoritmi si misura in ordini di grandezza, sia in termini di tempo che di dollari spesi su GPU cloud. Questo confronto mette a fianco le specifiche tecniche, i benchmark pubblici su hardware reale, i parametri raccomandati da OWASP e i casi concreti in cui framework e aziende hanno dovuto scegliere uno dei tre.

Cos’è l’hashing delle password e perché è ancora un problema nel 2026

L’hashing delle password trasforma una stringa in chiaro in un valore che non può essere invertito matematicamente. Un buon algoritmo aggiunge un sale casuale per ogni utente e un fattore di lavoro che rallenta deliberatamente il calcolo. Senza questo rallentamento, un database rubato diventa una lista di password in chiaro nel giro di ore: è esattamente quello che è successo a LinkedIn nel 2012, quando le password erano protette solo da SHA-1 senza sale.

Bcrypt, Argon2 e scrypt appartengono tutti alla categoria delle funzioni di derivazione di chiave lente (KDF), pensate apposta per essere costose da calcolare in massa. La differenza sostanziale tra loro riguarda quale risorsa hardware costringono l’attaccante a spendere: bcrypt punta soprattutto sul tempo di CPU, mentre Argon2 e scrypt aggiungono un requisito di memoria che rende molto meno conveniente l’uso di GPU e ASIC dedicati al cracking.

Nel 2026 questa distinzione pesa più che in passato. Le GPU consumer come la RTX 4090 calcolano decine di miliardi di hash SHA-256 al secondo, ma solo poche migliaia di hash bcrypt o Argon2id configurati correttamente. Capire quale algoritmo scegliere, e con quali parametri, resta quindi una delle decisioni di sicurezza più concrete che un team di sviluppo prende ogni giorno.

Il problema non riguarda solo chi scrive codice da zero. Ogni team che eredita un’applicazione più vecchia si trova prima o poi davanti alla stessa domanda: il database attuale usa ancora MD5 o SHA-1 senza sale? Usa bcrypt con un cost factor impostato dieci anni fa e mai più rivisto? La risposta cambia radicalmente il piano di lavoro, perché passare da un hash veloce a uno lento richiede una strategia di migrazione, non un semplice cambio di libreria. Per questo un confronto aggiornato tra bcrypt, Argon2id e scrypt serve tanto a chi lancia un progetto nuovo quanto a chi deve mettere in sicurezza un sistema esistente senza fermare il servizio.

Bcrypt: il veterano che protegge ancora metà del web

Bcrypt nasce nel 1999 dal lavoro di Niels Provos e David Mazières, costruito sopra il cifrario a blocchi Blowfish. La sua caratteristica principale è il cost factor, un numero che indica quante volte (2 elevato a quel numero) l’algoritmo ripete il proprio schedule di chiavi interno. Aumentare il cost factor di un’unità raddoppia il tempo di calcolo, il che rende semplice alzare la difficoltà nel tempo man mano che l’hardware diventa più veloce.

Il limite più citato di bcrypt riguarda la lunghezza dell’input: accetta al massimo 72 byte di password e tronca in silenzio tutto ciò che va oltre, un comportamento che ha causato più di un bug di sicurezza quando gli sviluppatori non lo sapevano. Bcrypt non richiede memoria significativa per funzionare, e proprio questo lo rende oggi meno resistente rispetto ad Argon2id e scrypt: una GPU può eseguire migliaia di istanze in parallelo senza saturare la propria memoria video.

Nonostante questo, bcrypt resta lo standard de facto in moltissimi framework. Ruby on Rails, attraverso la gemma Devise, lo usa come algoritmo predefinito con un cost factor di 11, che corrisponde a circa 250 millisecondi per hash su hardware server moderno. PHP lo imposta come valore di PASSWORD_DEFAULT nella funzione password_hash(), e dalla versione 8.4 il costo predefinito è salito da 10 a 12. Questa lunga adozione spiega perché OWASP lo consideri ancora accettabile, ma solo per sistemi legacy che già lo utilizzano.

Un altro aspetto tecnico spesso trascurato riguarda il formato dell’hash prodotto da bcrypt, che inizia sempre con un prefisso come $2a$, $2b$ o $2y$ seguito dal cost factor e dal sale codificato in Base64. Questo formato compatto ha reso bcrypt facile da integrare in database relazionali con un singolo campo di testo, un vantaggio pratico che ha contribuito alla sua diffusione capillare negli anni duemila e duemiladieci, ben prima che Argon2 esistesse anche solo come proposta accademica.

Argon2id: l’algoritmo che ha vinto la Password Hashing Competition

Argon2 è nato nel 2015 dal lavoro di Alex Biryukov, Daniel Dinu e Dmitry Khovratovich all’Università del Lussemburgo, ed è uscito vincitore dalla Password Hashing Competition, una gara pubblica internazionale organizzata proprio per individuare il successore di bcrypt e scrypt. Esistono tre varianti: Argon2d (ottimizzato contro attacchi GPU ma vulnerabile a side-channel), Argon2i (resistente ai side-channel ma più debole contro GPU) e Argon2id, un ibrido che combina i due approcci ed è oggi la variante raccomandata per quasi ogni scenario.

Argon2id espone tre parametri regolabili: la memoria (m, in KiB), il numero di iterazioni (t) e il grado di parallelismo (p). Il Password Storage Cheat Sheet di OWASP, aggiornato al 6 settembre 2026, indica come configurazione minima m=19456 KiB (19 MiB), t=2 e p=1, con alternative che vanno da 46 MiB con una sola iterazione fino a 7 MiB con cinque iterazioni per chi ha vincoli di memoria stringenti. L’algoritmo è oggi standardizzato nella RFC 9106 dell’IETF, pubblicata nel 2021, un dettaglio che mancava sia a bcrypt che a scrypt.

Il vantaggio pratico di Argon2id sta nel fatto di essere memory-hard by design: ogni istanza dell’algoritmo deve allocare decine di megabyte di RAM durante il calcolo. Una GPU con 24 GB di memoria video può quindi eseguire solo poche migliaia di istanze in parallelo invece di milioni, il che abbatte drasticamente il vantaggio economico del cracking su hardware grafico. Librerie come libsodium, il pacchetto argon2 di Node.js e l’estensione Argon2 di PHP lo implementano tutte con Argon2id come variante predefinita.

Va detto che Argon2id non è immune da limiti pratici. Su ambienti serverless o container con quote di memoria molto strette, allocare anche solo 19 MiB per ogni richiesta di login concorrente può costringere a ridimensionare l’infrastruttura, un dettaglio che i team DevOps devono valutare prima di alzare i parametri oltre il minimo raccomandato. È anche il motivo per cui OWASP pubblica una tabella di configurazioni alternative invece di un valore unico: permette di scegliere il punto di equilibrio più adatto al proprio hardware invece di imporre un compromesso identico per tutti.

Scrypt: memory-hard da prima che il termine fosse di moda

Scrypt precede Argon2 di sei anni: lo ha creato Colin Percival nel 2009 per proteggere il servizio di backup Tarsnap, ed è stato poi standardizzato nella RFC 7914 dell’IETF nel 2016. Era il primo algoritmo di hashing password pensato esplicitamente per richiedere grandi quantità di memoria, con l’obiettivo dichiarato di rendere antieconomico costruire hardware dedicato al cracking.

I suoi parametri sono N (costo CPU/memoria, sempre una potenza di due), r (dimensione del blocco) e p (parallelizzazione). OWASP nel 2026 raccomanda un minimo di N=2^17 (131.072), r=8 e p=1, una configurazione che richiede circa 128 MiB di RAM per singolo hash. È un requisito di memoria pesante, superiore a quello tipico di Argon2id al minimo OWASP, ma scrypt non ha mai vinto una competizione pubblica come Argon2 e la sua adozione nei framework web moderni resta più limitata.

Dove scrypt resta molto diffuso è fuori dal mondo delle password web: è alla base della funzione di proof-of-work di diverse criptovalute, tra cui Litecoin, proprio per la sua resistenza agli ASIC. Per l’hashing delle password nel 2026, OWASP lo colloca come seconda scelta, da usare quando Argon2id non è disponibile nello stack tecnologico scelto.

Node.js espone scrypt direttamente nel modulo nativo crypto, tramite la funzione crypto.scrypt(), senza bisogno di installare pacchetti esterni. Questo lo rende comodo per progetti che vogliono evitare dipendenze di terze parti, anche se la configurazione dei parametri N, r e p resta manuale e va allineata a mano ai minimi OWASP, mentre librerie come argon2 spesso offrono profili preconfigurati più semplici da adottare senza commettere errori.

Bcrypt vs Argon2id vs Scrypt: la tabella comparativa completa

La tabella riassume le differenze tecniche principali tra i tre algoritmi, con i parametri minimi raccomandati da OWASP nella versione 2026 del Password Storage Cheat Sheet.

CaratteristicaBcryptArgon2idScrypt
Anno di pubblicazione199920152009
Autore/origineNiels Provos, David MazièresBiryukov, Dinu, Khovratovich (Univ. Lussemburgo)Colin Percival
Base crittograficaCifrario a blocchi BlowfishFunzione dedicata memory-hardBasata su Salsa20/8
Vincitore Password Hashing CompetitionNo (precedente al PHC)Sì (2015)No (precedente al PHC)
Memory-hard by designNo
Parametro principaleCost factor (es. 12)Memoria (m), iterazioni (t), parallelismo (p)Costo N, block size r, parallelismo p
Configurazione minima OWASP 2026Cost factor ≥ 10m=19.456 KiB, t=2, p=1N=2^17, r=8, p=1 (~128 MiB)
Limite di lunghezza input72 byte (troncamento silenzioso)Nessun limite praticoNessun limite pratico
Standard IETFNessunoRFC 9106 (2021)RFC 7914 (2016)
Resistenza a GPU/ASICMediaAltaAlta
Raccomandazione OWASP 2026Solo sistemi legacyPrima sceltaAlternativa se Argon2id non disponibile
Supporto nativo diffusoPHP password_hash(), gemma bcrypt Rubylibsodium, PHP PASSWORD_ARGON2ID, npm argon2Node.js crypto.scrypt(), OpenSSL

Benchmark reali: quanto sono veloci su una GPU RTX 4090

I numeri più citati nel settore vengono da hashcat, lo strumento di cracking open source più usato dai penetration tester, nella sua versione 6.2.6. Un benchmark pubblicato sul forum ufficiale di hashcat e riportato in un gist tecnico dettagliato mostra, su una singola RTX 4090, una velocità di 184.000 hash al secondo per bcrypt al cost factor 5 (il valore predefinito del benchmark, non quello usato in produzione) e di 7.126 hash al secondo per scrypt con N=16384.

Questi numeri vanno riportati ai parametri realmente usati in produzione. Ogni incremento del cost factor di bcrypt raddoppia il lavoro richiesto: passare dal cost factor 5 del benchmark al 12 tipico di un’applicazione moderna significa dividere la velocità per 128, arrivando a circa 1.400 hash al secondo sulla stessa scheda. Lo stesso ragionamento si applica a scrypt: il salto da N=16384 al minimo OWASP di N=131072 comporta un fattore 8, portando la velocità stimata a circa 890 hash al secondo.

Per Argon2id non esiste ancora una riga di benchmark hashcat pubblica specifica per la configurazione minima OWASP (19 MiB, t=2) su RTX 4090, perché la natura memory-hard dell’algoritmo rende il porting su GPU molto più complesso rispetto a bcrypt o scrypt. I ricercatori che hanno provato a stimarlo collocano la velocità nell’ordine delle migliaia di hash al secondo anche su hardware di fascia alta, un valore paragonabile a scrypt ma ottenuto con un requisito di memoria per singola istanza generalmente più basso a parità di sicurezza.

Vale la pena guardare anche i numeri di riferimento per gli hash veloci, che spiegano perché algoritmi come MD5 o SHA-256 da soli non vadano mai usati per le password. Lo stesso benchmark hashcat v6.2.6 sulla RTX 4090 misura 164,1 GH/s per MD5 e 21.975,5 MH/s per SHA2-256, uno scarto di circa 892.000 volte rispetto ai 184.000 hash al secondo di bcrypt al cost factor 5. È la dimostrazione numerica del motivo per cui il breach LinkedIn del 2012, basato su SHA-1 senza sale, sia stato smontato in così poco tempo: un hash veloce progettato per l’integrità dei dati, non per resistere ad attacchi mirati, offre una protezione quasi nulla contro hardware moderno.

AlgoritmoConfigurazione testataVelocità su RTX 4090Fonte
MD5 (riferimento)164,1 GH/sBenchmark hashcat v6.2.6
SHA2-256 (riferimento)21.975,5 MH/sBenchmark hashcat v6.2.6
BcryptCost factor 5 (default benchmark)184.000 H/sForum hashcat, gist Chick3nman
Bcrypt (stima produzione)Cost factor 12~1.400 H/sCalcolo per scaling da hashcat
ScryptN=16.384 (2^14)7.126 H/sGist Chick3nman, hashcat v6.2.6
Scrypt (stima minimo OWASP)N=131.072 (2^17)~890 H/sCalcolo per scaling da hashcat
Argon2idm=19 MiB, t=2 (minimo OWASP)Ordine delle migliaia H/s, stima di settoreAnalisi comparative pubbliche

Il conto in dollari: quanto costa craccare una password nel 2026

Trasformare gli hash al secondo in un costo economico reale aiuta a capire perché la scelta dell’algoritmo non sia solo una questione accademica. Una guida di settore pubblicata nel 2026 da guptadeepak.com modella il tempo e la spesa su GPU cloud in affitto necessari per forzare un’unica password complessa di 8 caratteri (maiuscole, minuscole, numeri e simboli) protetta con i parametri minimi consigliati da OWASP per ciascun algoritmo.

Il divario tra i quattro schemi è netto. PBKDF2-HMAC-SHA256 a 600.000 iterazioni richiede circa 3 giorni e 5.000 dollari di calcolo cloud per una singola password. Bcrypt al cost factor 12 sale a circa 30 giorni e 40.000 dollari. Scrypt con N=2^17 arriva a circa 200 giorni e 300.000 dollari. Argon2id configurato a 128 MiB di memoria e 3 iterazioni, un livello più prudente del minimo OWASP, richiede stime vicine a 500 giorni e 750.000 dollari.

AlgoritmoConfigurazioneTempo stimato per craccareCosto GPU cloud stimato
PBKDF2-HMAC-SHA256600.000 iterazioni~3 giorni~5.000 $
BcryptCost factor 12~30 giorni~40.000 $
ScryptN=2^17, r=8, p=1~200 giorni~300.000 $
Argon2idm=128 MiB, t=3~500 giorni~750.000 $

Questi numeri assumono una password già abbastanza complessa da resistere a dizionari e attacchi ibridi, quindi da craccare per forza bruta pura. Contro password deboli o riutilizzate, ogni algoritmo cade in tempi molto più brevi: la scelta dell’hashing riduce il danno del riutilizzo di password, ma non lo elimina. Il report annuale di Hive Systems arriva a conclusioni simili modellando un rig da 12 GPU RTX 5090 contro bcrypt al cost factor 10, un altro promemoria di quanto l’hardware di cracking sia diventato accessibile.

Vale la pena leggere questi numeri anche al contrario, dal punto di vista di chi difende un servizio online. Se un attaccante deve spendere 750.000 dollari e 500 giorni per craccare una sola password Argon2id, un attacco su larga scala contro milioni di hash rubati diventa economicamente insostenibile per la maggior parte dei criminali informatici, che tendono a concentrare le risorse sugli obiettivi con il ritorno più rapido. Questo non significa che un database con hashing forte sia invulnerabile, ma sposta drasticamente il calcolo costi-benefici a sfavore dell’attaccante, soprattutto quando si combina con altre misure come il rate limiting sui tentativi di login e l’autenticazione a più fattori.

Cosa dice l’OWASP Password Storage Cheat Sheet nel 2026

Il Password Storage Cheat Sheet di OWASP, aggiornato al 6 settembre 2026, resta il riferimento più citato da auditor e responsabili sicurezza. Il documento stabilisce un ordine di preferenza netto: Argon2id come prima scelta con i parametri minimi già descritti, scrypt come alternativa se Argon2id non è disponibile nello stack, bcrypt riservato ai sistemi legacy che già lo utilizzano, e PBKDF2 riservato agli scenari che richiedono conformità FIPS-140.

Per PBKDF2, la guida indica 600.000 iterazioni con HMAC-SHA256, 220.000 con HMAC-SHA512 e 1.400.000 con HMAC-SHA1, quest’ultimo utilizzabile solo in configurazioni legacy da non replicare in nuovi progetti. Il documento gemello, il Cryptographic Storage Cheat Sheet, ricorda inoltre che per la cifratura asimmetrica la raccomandazione OWASP punta verso curve ellittiche moderne come Curve25519, un tema collegato ma distinto dall’hashing delle password.

Un dettaglio che spesso sfugge riguarda la storia recente di questi numeri: nel 2021 OWASP raccomandava ancora 310.000 iterazioni per PBKDF2-HMAC-SHA256, quasi la metà del valore attuale. L’aumento riflette la crescita della potenza di calcolo disponibile agli attaccanti, e implica che ogni configurazione va rivista periodicamente, non impostata una volta e dimenticata.

Per chi deve fare un audit di sicurezza su un’applicazione esistente, il primo passo pratico è quindi identificare l’algoritmo attualmente in uso guardando il prefisso dell’hash salvato nel database: $2a$, $2b$ o $2y$ indicano bcrypt, $argon2id$ indica Argon2id, mentre gli hash scrypt e PBKDF2 spesso vengono salvati insieme a metadati separati (sale, parametri) in colonne dedicate invece che in un’unica stringa. Solo dopo questo controllo ha senso decidere se e come pianificare una migrazione verso lo standard raccomandato da OWASP.

Chi usa cosa: Django, Rails, Spring Security, PHP e Node.js a confronto

Le scelte dei framework più diffusi raccontano come la teoria OWASP si traduce in pratica quotidiana. Django, il framework Python, usa PBKDF2-HMAC-SHA256 come hasher predefinito nella lista PASSWORD_HASHERS, con Argon2id, bcrypt e scrypt disponibili come opzioni secondarie. Il numero di iterazioni predefinito è salito da 600.000 nella versione 4.2 a 720.000 nella versione 5.0, un incremento che la documentazione ufficiale di Django motiva proprio con l’allineamento alle raccomandazioni OWASP più recenti. Per usare Argon2id su Django serve comunque installare la libreria esterna argon2-cffi, motivo per cui PBKDF2 resta il default di fabbrica.

Ruby on Rails, tramite la gemma Devise, punta tutto su bcrypt con un cost factor predefinito di 11, pari a circa 250 millisecondi per hash su hardware server tipico. Spring Security, nell’ecosistema Java, consiglia esplicitamente BCryptPasswordEncoder come implementazione preferita di PasswordEncoder, con una forza (log rounds) predefinita di 10 se non viene specificato altro, anche se molte guide del 2026 raccomandano di alzarla a 12 in nuovi progetti.

PHP resta l’esempio più diretto di evoluzione recente: la funzione password_hash() mappa PASSWORD_DEFAULT su bcrypt, e dalla versione 8.4 il costo predefinito è passato da 10 a 12, un cambiamento silenzioso che ha reso automaticamente più sicure milioni di applicazioni PHP senza che gli sviluppatori dovessero cambiare una riga di codice. Su Node.js, il pacchetto argon2 usa Argon2id come variante predefinita e distribuisce binari precompilati dalla versione 0.26.0 in poi, mentre il pacchetto bcrypt più diffuso ha raggiunto la major version 6.0.0.

Questo mosaico di scelte diverse spiega perché non esista un algoritmo “sbagliato” in assoluto, ma solo scelte più o meno allineate alle raccomandazioni correnti. Un’applicazione Django che usa PBKDF2 di default non è insicura, ma un team che vuole il massimo livello di protezione dovrà installare esplicitamente argon2-cffi e cambiare la configurazione, un passaggio che nella pratica molti progetti rimandano per anni. La differenza tra un default sicuro e un default che richiede intervento manuale pesa più di quanto sembri, perché la maggior parte degli sviluppatori non tocca mai le impostazioni di autenticazione dopo il primo rilascio in produzione.

Prezzi e licenze: tutto open source, ma non tutto gratis da eseguire

Bcrypt, Argon2 e scrypt sono tutti algoritmi open source, senza licenze da pagare e senza brevetti attivi che ne limitino l’uso commerciale. Il costo reale non sta nell’acquisto ma nel calcolo: ogni login legittimo deve eseguire lo stesso hash che si vuole rendere costoso per un attaccante, quindi la scelta dei parametri è sempre un compromesso tra sicurezza e carico sui server di produzione.

Bcrypt e PBKDF2 hanno un impatto trascurabile sulla RAM del server, il che li rende comodi in ambienti con memoria limitata o con molti login simultanei su hardware condiviso. Argon2id e scrypt, per design, richiedono decine o centinaia di megabyte di RAM per ogni hash calcolato: su un server che gestisce migliaia di login al secondo, questo può tradursi in un bisogno concreto di più memoria fisica, un costo infrastrutturale che va messo in conto insieme a quello di sicurezza. Alcuni provider di cloud KMS e HSM offrono servizi a pagamento per la protezione delle chiavi crittografiche, ma restano strumenti complementari e non sostituiscono l’hashing delle password lato applicativo.

Cinque casi reali dove l’algoritmo di hashing ha fatto la differenza

La teoria diventa concreta quando si guardano le decisioni prese da progetti reali. Cinque esempi documentati mostrano come la scelta dell’algoritmo di hashing passi dalla carta alla pratica.

  • LinkedIn, 2012: le password erano protette solo da SHA-1 senza sale, un algoritmo veloce non pensato per questo scopo. Secondo Have I Been Pwned il breach ha coinvolto 164,6 milioni di account, e diverse fonti dell’epoca, riportate anche da Wikipedia, stimano che la maggior parte degli hash sia stata craccata entro pochi giorni dalla pubblicazione. È il caso di scuola più citato per spiegare perché un hash veloce e senza sale non basta.
  • Django e l’aumento delle iterazioni PBKDF2: il progetto ha alzato il numero di iterazioni predefinito da 600.000 a 720.000 tra le versioni 4.2 e 5.0, seguendo l’evoluzione delle raccomandazioni OWASP invece di lasciare un valore fisso nel tempo.
  • PHP 8.4 e il cost factor di bcrypt: il linguaggio ha alzato il costo predefinito di password_hash() da 10 a 12, aggiornando automaticamente la sicurezza di ogni applicazione che si affida al valore di default.
  • Keycloak e il dibattito sulla community: nella issue #16629 su GitHub, gli sviluppatori hanno discusso apertamente la necessità di alzare le iterazioni PBKDF2 predefinite del progetto per allinearle alle nuove raccomandazioni OWASP, un esempio di come la manutenzione della sicurezza richieda revisioni continue anche nei progetti open source più maturi.
  • Actual Budget e la migrazione ad Argon2id: la pull request #7829 di questo progetto open source di gestione budget documenta il passaggio esplicito da bcrypt ad Argon2id, motivato citando testualmente la posizione OWASP secondo cui bcrypt andrebbe usato solo nei sistemi legacy dove Argon2 e scrypt non sono disponibili.

Guida alla migrazione: passare da bcrypt o PBKDF2 ad Argon2id

Cambiare algoritmo di hashing non richiede di forzare il reset delle password di tutti gli utenti. La tecnica standard, adottata anche nel caso di Actual Budget citato sopra, si chiama lazy rehashing: il vecchio hash resta valido finché l’utente non effettua un login, momento in cui viene sostituito in modo trasparente con quello nuovo.

  1. Aggiungi la libreria Argon2id al progetto (ad esempio il pacchetto argon2 su Node.js o argon2-cffi su Django).
  2. Mantieni la libreria del vecchio algoritmo (bcrypt o PBKDF2) attiva solo per la verifica, non per nuovi hash.
  3. Al momento del login, verifica la password con l’algoritmo memorizzato nel database, identificabile dal prefisso dell’hash.
  4. Se la verifica ha successo, ricalcola l’hash della stessa password con Argon2id e sovrascrivi il valore salvato.
  5. Imposta Argon2id come algoritmo predefinito per tutte le nuove registrazioni.
  6. Calibra i parametri (m, t, p) sul tuo hardware reale, puntando a un tempo di calcolo tra 250 e 500 millisecondi per hash.
  7. Esegui un test di carico che simuli il picco di login concorrenti prima del rilascio in produzione.
  8. Monitora l’uso di CPU e RAM dei server di autenticazione nelle prime settimane dopo il rilascio.
  9. Documenta la data di taglio: dopo un periodo ragionevole (es. 12-18 mesi) valuta se forzare il reset per gli account rimasti sul vecchio algoritmo.

Un esempio semplificato in Node.js della logica di verifica e rehash automatico:

const argon2 = require('argon2');
const bcrypt = require('bcrypt');

async function verificaEAggiorna(utente, passwordInserita) {
  const hashSalvato = utente.passwordHash;
  let valida = false;

  if (hashSalvato.startsWith('$2')) {
    // hash legacy in formato bcrypt
    valida = await bcrypt.compare(passwordInserita, hashSalvato);
    if (valida) {
      utente.passwordHash = await argon2.hash(passwordInserita, { type: argon2.argon2id });
      await utente.save();
    }
  } else {
    // hash gia' in Argon2id
    valida = await argon2.verify(hashSalvato, passwordInserita);
  }

  return valida;
}

Il vantaggio di questo approccio è che non serve mai comunicare agli utenti un reset forzato, evitando l’attrito e il calo di conversione che spesso accompagna quel tipo di comunicazione. Lo svantaggio è che gli account inattivi restano protetti dal vecchio algoritmo finché non tornano a fare login, quindi vale la pena affiancare un piano B per chi non si collega più da tempo.

Pro e contro di bcrypt, Argon2id e scrypt

Bcrypt. Pro: supporto nativo in quasi ogni linguaggio, 25 anni di verifica pubblica, basso uso di memoria, semplice da configurare con un solo parametro. Contro: nessuna resistenza specifica alla memoria, limite di 72 byte con troncamento silenzioso, nessuno standard IETF ufficiale, sempre più debole rispetto alle GPU moderne ai cost factor tipici.

Argon2id. Pro: raccomandazione principale di OWASP, standardizzato in RFC 9106, resistenza elevata sia a GPU che ad ASIC, tre parametri regolabili per adattarsi a hardware diverso. Contro: richiede più memoria per singolo hash, meno librerie native rispetto a bcrypt in linguaggi più vecchi, tuning dei parametri più complesso per chi non ha esperienza pregressa.

Scrypt. Pro: memory-hard fin dal 2009, standard IETF (RFC 7914), ampiamente testato nel mondo delle criptovalute. Contro: mai vincitore di una competizione crittografica pubblica come Argon2, adozione più limitata nei framework web recenti, requisito di memoria minimo OWASP (circa 128 MiB) superiore a quello di Argon2id a parità di sicurezza percepita.

PBKDF2, pur non essendo il protagonista principale di questo confronto, merita una menzione a parte perché resta l’unico dei quattro algoritmi con una copertura esplicita negli standard FIPS-140. Pro: supporto nativo in praticamente ogni libreria crittografica, incluse quelle certificate per ambienti regolamentati, configurazione basata su un solo parametro (il numero di iterazioni). Contro: nessuna resistenza alla memoria, il che lo rende il più economico da attaccare su GPU tra i quattro a parità di tempo di calcolo per l’utente legittimo.

Quale scegliere: cinque casi d’uso concreti

  • Nuova applicazione SaaS senza vincoli legacy: Argon2id con i parametri minimi OWASP, aumentando memoria e iterazioni in base al budget dei server di autenticazione.
  • Sistema esistente con milioni di hash bcrypt già in produzione: mantenere bcrypt, alzare subito il cost factor al valore massimo sostenibile e avviare una migrazione lazy verso Argon2id parallela ai login.
  • Ambiente regolamentato che richiede conformità FIPS-140 (settore bancario, pubblica amministrazione): PBKDF2-HMAC-SHA256 con almeno 600.000 iterazioni, l’unica opzione tra le quattro esplicitamente coperta dagli standard FIPS.
  • Applicazione mobile o dispositivo con RAM limitata: bcrypt resta più semplice da eseguire senza saturare la memoria del dispositivo, oppure Argon2id con parametri di memoria ridotti (7-12 MiB) tra quelli previsti da OWASP per scenari vincolati.
  • Server multi-tenant con molti login concorrenti: attenzione al rischio di denial of service accidentale con Argon2id o scrypt configurati troppo aggressivamente, va dimensionata la memoria disponibile prima di alzare i parametri, con test di carico specifici prima del rilascio.

Un sesto scenario, sempre più comune nel 2026, riguarda le applicazioni che devono gestire sia utenti finali sia account di servizio machine-to-machine. In questi casi molti team scelgono di applicare Argon2id solo alle password umane, che vengono digitate raramente, e di usare token o chiavi API con rotazione automatica per le comunicazioni tra sistemi, evitando di applicare hashing lento a credenziali che devono essere verificate migliaia di volte al secondo tra microservizi interni.

Il verdetto finale: chi vince nel 2026

I numeri raccolti in questo confronto puntano tutti nella stessa direzione. Argon2id offre oggi il miglior rapporto tra costo di cracking e costo di gestione per la maggior parte delle applicazioni nuove: una stima di settore lo colloca a circa 750.000 dollari e 500 giorni per forzare una singola password complessa, contro i 40.000 dollari e 30 giorni di bcrypt allo stesso livello di robustezza percepita. È anche l’unico dei tre ad avere sia il titolo di vincitore della Password Hashing Competition sia uno standard IETF dedicato.

Bcrypt resta una scelta accettabile per chi gestisce sistemi legacy o ha vincoli di memoria stringenti, ma OWASP lo colloca ormai in coda alla lista delle raccomandazioni per nuovi progetti. Scrypt occupa una posizione intermedia solida, soprattutto dove Argon2id non è disponibile nello stack tecnologico, mentre PBKDF2 mantiene un ruolo specifico e insostituibile solo negli scenari che richiedono conformità FIPS-140. La scelta pratica per chi scrive codice nuovo nel 2026 è quasi sempre la stessa: partire da Argon2id, calibrare i parametri sul proprio hardware e rivedere quella configurazione ogni volta che le raccomandazioni OWASP vengono aggiornate.

Chi gestisce un sistema esistente non deve vedere questo confronto come un obbligo a riscrivere tutto entro la settimana. Bcrypt configurato con un cost factor alto resta una difesa ragionevole, e una migrazione pianificata con calma, testata sotto carico e distribuita nel tempo batte quasi sempre un cambio affrettato fatto sotto pressione dopo un incidente. La cosa più importante resta comunque sapere con precisione quale algoritmo protegge oggi le password dei propri utenti, invece di darlo per scontato.

Domande frequenti

Qual è il miglior algoritmo di hashing delle password nel 2026?
Per la maggior parte dei nuovi progetti è Argon2id, la prima scelta indicata dal Password Storage Cheat Sheet di OWASP, con parametri minimi di 19 MiB di memoria, 2 iterazioni e parallelismo 1.

Bcrypt è ancora sicuro nel 2026?
Sì, se configurato con un cost factor di almeno 12 e se usato in sistemi che già lo adottano. OWASP lo considera comunque un’opzione legacy, non la prima scelta per un progetto nuovo.

Perché Argon2id è considerato più sicuro di scrypt?
Entrambi sono memory-hard, ma Argon2id ha vinto una competizione pubblica internazionale dedicata proprio a questo confronto, è standardizzato in una RFC IETF dedicata (9106) e offre un controllo più fine su memoria, iterazioni e parallelismo.

Cosa succede se una password supera i 72 byte con bcrypt?
Bcrypt tronca in silenzio tutto ciò che eccede i 72 byte, senza generare un errore. Password molto lunghe possono quindi risultare equivalenti tra loro oltre quel limite, un dettaglio da verificare sempre prima di adottarlo.

Devo forzare il reset delle password quando migro ad Argon2id?
Non è necessario. La tecnica del lazy rehashing permette di sostituire l’hash in modo trasparente al primo login successivo alla migrazione, senza interrompere l’esperienza dell’utente.

Quanto costa in termini di CPU e RAM passare ad Argon2id?
Dipende dai parametri scelti, ma alla configurazione minima OWASP (19 MiB, 2 iterazioni) il costo aggiuntivo per singolo login resta contenuto. Il calcolo va comunque testato sotto carico prima del rilascio, perché la memoria richiesta si somma per ogni login concorrente.

PBKDF2 è ancora accettabile nel 2026?
Sì, ma solo per scenari che richiedono conformità FIPS-140, con almeno 600.000 iterazioni su HMAC-SHA256. Per progetti senza questo vincolo normativo, OWASP consiglia Argon2id o scrypt.

Che differenza c’è tra Argon2i, Argon2d e Argon2id?
Argon2d è ottimizzato contro attacchi basati su GPU ma più esposto ad attacchi side-channel. Argon2i è resistente ai side-channel ma più debole contro GPU. Argon2id combina i due meccanismi ed è la variante raccomandata da OWASP per la quasi totalità degli usi legati all’hashing delle password.