MD5 vs SHA-256: quale algoritmo hash dovresti usare?
L’hashing è una delle operazioni più fondamentali nell’informatica, eppure scegliere l’algoritmo sbagliato può esporre il tuo sistema ad attacchi di collisione, corruzione dei dati o overhead prestazionale inutile. Questa guida confronta i quattro algoritmi hash più diffusi e ti dà un framework decisionale chiaro.
Cos’è una funzione hash?
Una funzione hash crittografica prende dati di input arbitrari e produce un output di dimensione fissa (il “digest” o “hash”). Le buone funzioni hash hanno tre proprietà:
- Deterministica: lo stesso input produce sempre lo stesso output.
- A senso unico: non puoi invertire l’hash per recuperare l’input originale.
- Resistente alle collisioni: dovrebbe essere computazionalmente irrealizzabile trovare due input diversi che producano lo stesso hash.
Quando la proprietà n.3 si rompe, l’algoritmo è considerato “crittograficamente compromesso”: è esattamente ciò che è successo a MD5 e SHA-1.
Confronto algoritmi a colpo d’occhio
| Proprietà | MD5 | SHA-1 | SHA-256 | SHA-512 |
|---|---|---|---|---|
| Dimensione output | 128 bit (32 caratteri hex) | 160 bit (40 caratteri hex) | 256 bit (64 caratteri hex) | 512 bit (128 caratteri hex) |
| Dimensione blocco | 512 bit | 512 bit | 512 bit | 1024 bit |
| Anno di introduzione | 1991 | 1995 | 2001 | 2001 |
| Progettista | Ron Rivest | NSA / NIST | NSA / NIST | NSA / NIST |
| Resistenza alle collisioni | Compromesso (2004) | Compromesso (2017) | Sicuro | Sicuro |
| Velocità (relativa) | Più veloce | Veloce | Moderato | Moderato (più veloce su 64 bit) |
| Stato NIST | Deprecato | Deprecato | Raccomandato | Raccomandato |
MD5: veloce ma compromesso
MD5 (Message-Digest Algorithm 5) è stato progettato da Ronald Rivest nel 1991 ed è diventato lo standard de facto per i checksum negli anni ‘90 e nei primi anni 2000. Produce un hash a 128 bit in 32 caratteri esadecimali.
Perché MD5 è compromesso
Nel 2004, Xiaoyun Wang ha dimostrato attacchi di collisione pratici contro MD5. Nel 2008, i ricercatori hanno creato un certificato SSL malevolo usando collisioni MD5, dimostrando che l’attacco non era solo teorico. Oggi, le collisioni MD5 possono essere generate in pochi secondi su hardware consumer.
// Genera un hash MD5 (solo per uso non legato alla sicurezza)
// L'API Web Crypto non è disponibile per MD5 — usa una libreria
import { md5 } from 'hash-wasm';
const hash = await md5('Hello, World!');
console.log(hash);
// → 'bea8252ff4e80f41719ea13cdf007273' (32 caratteri hex)
Quando MD5 è ancora accettabile
Nonostante sia crittograficamente compromesso, MD5 rimane utile per applicazioni non legate alla sicurezza:
- Deduplicazione di file: rilevare file duplicati nei sistemi di storage
- Chiavi di cache: generare chiavi corte e deterministiche per i lookup di cache
- Checksum di integrità dei dati: verifica rapida che i dati non siano stati corrotti accidentalmente (non manomessi deliberatamente)
- Compatibilità con sistemi legacy: interoperare con sistemi più vecchi che richiedono MD5
La distinzione chiave: MD5 protegge dalla corruzione accidentale ma non dalla manipolazione deliberata.
SHA-1: deprecato ma persistente
SHA-1 (Secure Hash Algorithm 1) è stato progettato dalla NSA e pubblicato dal NIST nel 1995. Produce un hash a 160 bit in 40 caratteri esadecimali.
Nel 2017, Google e CWI Amsterdam hanno dimostrato la prima collisione SHA-1 pratica (l’attacco “SHAttered”), generando due file PDF diversi con lo stesso hash SHA-1. I principali browser e autorità di certificazione avevano già iniziato a rifiutare i certificati SHA-1 nel 2016.
Usa SHA-1 solo per la compatibilità con sistemi che lo richiedono (es. Git usa SHA-1 per gli hash dei commit, anche se sta passando a SHA-256). Per qualsiasi nuovo sviluppo, scegli SHA-256 o più forte.
SHA-256: lo standard attuale
SHA-256 fa parte della famiglia SHA-2, progettata dalla NSA e pubblicata dal NIST nel 2001. Produce un hash a 256 bit in 64 caratteri esadecimali ed è l’algoritmo raccomandato per virtualmente tutte le esigenze di hashing nel 2026.
// Genera un hash SHA-256 usando l'API Web Crypto (nativa nel browser)
async function sha256(text) {
const data = new TextEncoder().encode(text);
const hash = await crypto.subtle.digest('SHA-256', data);
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
const hash = await sha256('Hello, World!');
console.log(hash);
// → 'dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f'
Perché SHA-256 è la scelta predefinita
- Nessun attacco noto: a partire dal 2026, non esistono attacchi pratici di collisione o preimage
- Nativo nel browser: disponibile via API Web Crypto in tutti i browser moderni — nessuna libreria necessaria
- Standard industriale: usato da certificati TLS, Bitcoin, gestori di pacchetti (npm, pip), digest di immagini Docker e dalla maggior parte dei sistemi di verifica dell’integrità
- Approvato dal NIST: raccomandato per tutte le applicazioni sensibili alla sicurezza
SHA-512: quando ti serve di più
SHA-512 produce un hash a 512 bit in 128 caratteri esadecimali. Usa una dimensione di blocco a 1024 bit (vs i 512 bit di SHA-256), il che lo rende più veloce di SHA-256 sui processori a 64 bit perché elabora più dati per ciclo.
# Python: SHA-512 è semplice quanto SHA-256
import hashlib
hash_256 = hashlib.sha256(b'Hello, World!').hexdigest()
hash_512 = hashlib.sha512(b'Hello, World!').hexdigest()
print(f"SHA-256: {hash_256}") # 64 caratteri
print(f"SHA-512: {hash_512}") # 128 caratteri
Usa SHA-512 quando:
- Ti serve un margine di sicurezza maggiore (resistenza alle collisioni a 256 bit vs 128 bit per SHA-256)
- La tua piattaforma è a 64 bit e le prestazioni contano (SHA-512 può essere 1.5× più veloce di SHA-256 su x86-64)
- Il protocollo o la specifica lo richiede (alcuni schemi di certificati, requisiti specifici di compliance)
Per la maggior parte delle applicazioni, SHA-256 è sufficiente. La lunghezza extra degli hash SHA-512 raddoppia storage e larghezza di banda senza un beneficio pratico di sicurezza per i casi d’uso tipici.
Framework decisionale: quale hash usare
Per integrità dei file e checksum
Usa SHA-256. È lo standard per verificare i download, confrontare contenuti di file e assicurarsi che i dati non siano corrotti. Se stai sostituendo un sistema esistente basato su MD5, SHA-256 è l’aggiornamento drop-in.
# Verifica l'integrità di un download
sha256sum downloaded-file.tar.gz
# Confronta l'output con l'hash pubblicato
Per la memorizzazione di password
Non usare né MD5 né SHA-256 direttamente. Le funzioni hash generaliste sono troppo veloci per l’hashing delle password: un attaccante può tentare miliardi di tentativi al secondo. Usa invece un algoritmo di hashing delle password dedicato:
| Algoritmo | Stato | Note |
|---|---|---|
| Argon2id | Raccomandato | Vincitore della Password Hashing Competition 2015; memory-hard |
| bcrypt | Buono | Largamente supportato; salt integrato; work factor regolabile |
| scrypt | Buono | Memory-hard; usato da alcuni sistemi di criptovaluta |
| PBKDF2 | Accettabile | Approvato NIST ma non memory-hard; usa ≥600.000 iterazioni |
| SHA-256 | Inadeguato | Troppo veloce; nessun salt integrato; vulnerabile ad attacchi GPU |
| MD5 | Pericoloso | Compromesso + troppo veloce; banalmente craccato |
// SBAGLIATO: non fare l'hash delle password con SHA-256
const hash = await sha256(password); // Craccabile a miliardi/sec
// CORRETTO: usa bcrypt (esempio Node.js)
import bcrypt from 'bcrypt';
const hash = await bcrypt.hash(password, 12); // 12 round = ~250ms
const isValid = await bcrypt.compare(input, hash);
Per HMAC e autenticazione dei messaggi
Usa SHA-256 con HMAC. HMAC (Hash-based Message Authentication Code) combina una funzione hash con una chiave segreta per verificare sia integrità sia autenticità:
// HMAC-SHA256 per verifica della firma di un webhook
async function verifyWebhook(payload, signature, secret) {
const key = await crypto.subtle.importKey(
'raw', new TextEncoder().encode(secret),
{ name: 'HMAC', hash: 'SHA-256' }, false, ['verify']
);
const sig = Uint8Array.from(atob(signature), c => c.charCodeAt(0));
return crypto.subtle.verify('HMAC', key, sig, new TextEncoder().encode(payload));
}
Per storage indirizzato dal contenuto
Usa SHA-256. Git, Docker e IPFS usano tutti storage indirizzato dal contenuto in cui l’hash del contenuto funge da indirizzo. SHA-256 fornisce sufficiente resistenza alle collisioni per garantire l’unicità su miliardi di oggetti.
Benchmark prestazionali
Velocità di hashing relativa su un processore x86-64 moderno (più alto = più veloce):
| Algoritmo | Throughput (MB/s) | Velocità relativa |
|---|---|---|
| MD5 | ~3,200 | 1.0× (baseline) |
| SHA-1 | ~2,400 | 0.75× |
| SHA-256 | ~1,500 | 0.47× |
| SHA-512 | ~2,100 | 0.66× |
Nota: SHA-512 è più veloce di SHA-256 sui processori a 64 bit grazie al suo stato interno più ampio. Sui sistemi a 32 bit la situazione si inverte. Per la maggior parte delle applicazioni la differenza di velocità è irrilevante: fare l’hash di un file da 1 MB richiede meno di 1 ms con uno qualsiasi di questi algoritmi.
Errori comuni da evitare
1. Usare MD5 per la sicurezza
Le collisioni MD5 sono banali da generare. Non usare mai MD5 per firme digitali, validazione di certificati o qualsiasi scenario in cui un attaccante possa elaborare un input malevolo.
2. Fare l’hash delle password con SHA-256
SHA-256 non è un hash per password. È troppo veloce, non ha salt integrato ed è vulnerabile a rainbow table e attacchi brute force accelerati da GPU. Usa Argon2id o bcrypt. Per capire perché, vedi la nostra guida sull’entropia delle password: spiega la matematica dietro la resistenza alla forza bruta.
3. Assumere che la lunghezza dell’hash equivalga alla sicurezza
Un hash a 512 bit non è automaticamente “più sicuro” di un hash a 256 bit per la resistenza alle collisioni. Il margine di sicurezza di SHA-256 (resistenza alle collisioni a 128 bit) è già molto oltre la capacità di forza bruta. Scegli in base ai tuoi requisiti effettivi, non alla lunghezza dell’hash.
4. Inventare combinazioni di hash personali
Pattern come SHA256(MD5(data)) o MD5(data + salt) non aggiustano magicamente un algoritmo compromesso. Usa un singolo algoritmo ben verificato (SHA-256) o una costruzione adeguata (HMAC) invece.
Provalo
Genera e confronta hash MD5, SHA-1, SHA-256 e SHA-512 istantaneamente con il nostro Generatore di Hash — incolla testo o trascina un file, e vedi tutti e quattro i digest affiancati. 100% nel tuo browser, nessun dato lascia mai il tuo dispositivo.
Per uno sguardo più ampio sulla sicurezza web inclusi autenticazione, validazione dell’input e header di sicurezza, leggi la nostra guida Web Security Essentials. Puoi anche esplorare tutti i nostri strumenti essenziali per sviluppatori per codifica, hashing e conversione dati.
Domande frequenti
MD5 è ancora sicuro per i checksum?
MD5 è sicuro per rilevare la corruzione accidentale dei file: se un file è danneggiato durante il download, l’hash MD5 cambierà quasi sicuramente. Tuttavia, MD5 non è sicuro contro la manomissione deliberata perché un attaccante può elaborare un file modificato con lo stesso hash MD5. Per la verifica dell’integrità in cui gli avversari sono una preoccupazione (es. distribuzione di software), usa invece SHA-256.
Quanto è più lento SHA-256 rispetto a MD5?
SHA-256 è circa 2× più lento di MD5 in throughput grezzo. Su hardware moderno, MD5 calcola hash a circa 3.200 MB/s mentre SHA-256 a circa 1.500 MB/s. In pratica, questa differenza è trascurabile per la maggior parte delle applicazioni: fare l’hash di un file da 100 MB richiede circa 70 ms con SHA-256. Il divario di prestazioni conta solo per scenari ad altissimo throughput come ispezione di pacchetti di rete o deduplicazione di storage su scala.
Dovrei usare SHA-256 o SHA-512 per la mia applicazione?
Usa SHA-256 per la maggior parte delle applicazioni: fornisce resistenza alle collisioni a 128 bit, ben oltre la capacità di forza bruta. Scegli SHA-512 se: (a) la tua piattaforma è a 64 bit e ti serve il massimo throughput, (b) una specifica o un requisito di compliance lo impone, oppure (c) vuoi un margine di sicurezza più ampio per l’integrità dei dati a lungo termine. La lunghezza extra dell’hash di SHA-512 raddoppia lo storage ed è raramente necessaria.
SHA-256 può essere craccato o invertito?
SHA-256 non può essere invertito: è una funzione a senso unico. A partire dal 2026, non esistono attacchi pratici di preimage o collisione contro SHA-256. Il miglior attacco noto richiede 2^128 operazioni per le collisioni, che è computazionalmente irrealizzabile con la tecnologia attuale o prevedibile. SHA-256 è approvato dal NIST e usato in infrastrutture critiche tra cui TLS, Bitcoin e sistemi federali.
Perché alcuni sistemi usano ancora MD5 se è compromesso?
La compatibilità legacy è il motivo principale. Molti sistemi, protocolli e formati di file esistenti sono stati progettati attorno a MD5 prima che le sue debolezze fossero scoperte. Migrare richiede modifiche coordinate su tutti i componenti. Per usi non legati alla sicurezza come chiavi di cache e deduplicazione, il vantaggio di velocità di MD5 e l’output più corto lo rendono una scelta pragmatica dove gli attacchi di collisione non sono una preoccupazione del modello di minaccia.