Cos'e' l'Hashing#
Una funzione di hashing prende un input di qualsiasi dimensione e produce un output di lunghezza fissa (il digest) in modo deterministico e non invertibile. E' la base dell'integrita' dei dati: se anche un solo byte del file cambia, l'hash cambia completamente. Non e' crittografia — non serve una chiave e non si decifra nulla.

Funzione one-way che trasforma un input di qualsiasi dimensione in un digest di lunghezza fissa. Usato per verificare integrita' dei dati. Non e' cifratura — non c'e' chiave, non c'e' decifratura.
TL;DR#
Hashing risolve una domanda: "questo dato e' arrivato intatto?". Non risponde a "chi l'ha mandato?" (serve HMAC o firma digitale) e non protegge la riservatezza (serve cifratura).
- SHA-256: 256 bit, 64 char hex. Standard NIST. Per integrita' file, firme digitali, TLS.
- SHA-3 (Keccak): design diverso da SHA-2, concorso NIST 2015. Alternativa se SHA-2 fosse compromessa.
- MD5: 128 bit, cracked 2004. Solo per checksum veloci non crittografici.
- SHA-1: deprecated 2017 (SHAttered attack). Non usare per sicurezza.
Gli hash si leggono in esadecimale: 1 char hex = 4 bit. SHA-256 = 256 bit = 64 char hex.
HMAC#
HMAC (Hash-based Message Authentication Code) combina un hash con una chiave segreta condivisa. L'hash semplice garantisce solo integrita' — chiunque puo' ricalcolare l'hash di un messaggio modificato. HMAC aggiunge autenticazione: solo chi conosce la shared key puo' produrre l'HMAC corretto. Senza la chiave, l'attaccante non puo' falsificare il codice anche se modifica il messaggio.
sequenceDiagram
participant M as Mittente
participant A as Attaccante MITM
participant R as Ricevente
Note over M,R: Condividono shared_key (scambiata in anticipo)
M->>M: HMAC = SHA256(shared_key + messaggio)
M->>A: messaggio + HMAC
A->>A: Modifica il messaggio
A->>A: Tenta di ricalcolare HMAC senza shared_key
Note over A: IMPOSSIBILE senza la chiave
A->>R: messaggio_modificato + HMAC_originale
R->>R: Ricalcola SHA256(shared_key + messaggio_ricevuto)
Note over R: HMAC calcolato != HMAC ricevuto
Note over R: Manomissione rilevata
Lettura: Mittente e ricevente condividono la secret key. Il mittente calcola HMAC e lo invia con il messaggio. L'attaccante modifica il messaggio ma non riesce a produrre un HMAC valido senza la chiave. Il ricevente ricalcola l'HMAC sul messaggio ricevuto — il mismatch rivela la manomissione.

Dev parallel: in PHP
hash_hmac('sha256', $payload, $secret)e' esattamente quello che usi per verificare i webhook di Stripe o GitHub. Prima di processare un ordine ricevuto via webhook, calcoli l'HMAC del body con il secret che Stripe ti ha dato in dashboard — se corrisponde all'X-Stripe-Signaturenell'header, il payload e' autentico. In Node.js e'crypto.createHmac('sha256', secret).update(payload).digest('hex'). Stesso concetto che usa TLS per ogni record (integrity check sul pacchetto dati) e IPsec per ogni pacchetto cifrato.
Password Hashing#
Nessun sistema corretto salva la password in chiaro. Salva l'hash. Al login, ricalcola l'hash della password inserita e confronta. Il problema fondamentale e' che un hash veloce (MD5, SHA-1) diventa un vettore di attacco se il database viene compromesso.
graph LR
PWD["password123"]
SALT["salt casuale
x7kQ9m"]
BCRYPT["bcrypt
cost=10
2^10 iterazioni"]
HASH["$2y$10$x7kQ9m...
hash salvato nel DB"]
CRACK["Attaccante
ha il DB"]
RT["Rainbow Table
MD5 690 GB"]
FAIL["FAIL
salt rende la
tabella inutile"]
PWD --> BCRYPT
SALT --> BCRYPT
BCRYPT --> HASH
CRACK -->|cerca| RT
RT -->|ma| FAIL
Lettura: La password viene combinata con un salt casuale e processata da bcrypt (con 2^10 iterazioni). Il risultato — che include il salt — viene salvato nel DB. Un attaccante che ruba il DB e tenta di usare una rainbow table precalcolata fallisce: il salt rende l'hash unico per quell'utente, la tabella non serve.
Rainbow Tables e Salting#
Una rainbow table e' un database precalcolato che mappa hash → password originale. Il costo computazionale viene pagato una volta sola da chi costruisce la tabella: poi ogni ricerca e' O(1), istantanea. Il salting e' la contromisura diretta: un valore casuale univoco aggiunto a ogni password prima dell'hash rende ogni entry nel DB impossibile da pre-calcolare.
Senza salt:
hash("password123") = 482c811... (uguale per TUTTI gli utenti)
→ un'unica rainbow table colpisce TUTTI
Con salt univoco per ogni utente:
hash("password123" + "x7kQ9m") = a93f2b1... (utente Mario)
hash("password123" + "p3mX2k") = f71c4e8... (utente Luigi)
→ stessa password, hash completamente diversi
→ la rainbow table non serve: dovrebbe coprire ogni salt possibileIl salt non e' un segreto e non serve tenerlo nascosto: va salvato nel DB perche' serve per ricalcolare l'hash al login. Il suo scopo e' solo rendere ogni hash unico — non aggiunge segreto, aggiunge randomness.
Key Stretching#
Il salting neutralizza le rainbow tables ma non rallenta il brute force diretto. Su un dump del DB, Hashcat con GPU moderna processa miliardi di hash MD5/secondo. Il key stretching risolve questo: applica la funzione di hashing migliaia o milioni di volte (iterazioni), rendendo ogni singolo tentativo deliberatamente costoso.
Algoritmi a confronto:
| Algoritmo | Scopo | Veloce? | Sale? | Iterazioni | Uso tipico |
|---|---|---|---|---|---|
| MD5 | Checksum (NON sicurezza) | Si' (deprecated) | No | 1 | Legacy, da rimuovere |
| SHA-256 | Integrita' file, firme | Si' | No | 1 | TLS, certificati, IOC |
| SHA-3 | Integrita', alternativa SHA-2 | Si' | No | 1 | Standard NIST moderno |
| bcrypt | Password storage | No (by design) | Si' (embedded) | 2^cost | Linux, web app |
| PBKDF2 | Password + key derivation | No (by design) | Si' | Configurabile (1M+) | WPA2, iOS, FIPS |
| Argon2id | Password storage moderno | No (by design) | Si' | + memory | Sistemi nuovi |
Dev parallel: ogni volta che chiami
password_hash($password, PASSWORD_BCRYPT)in PHP obcrypt.hash(password, 10)in Node.js, stai usando key stretching senza saperlo. L'algoritmo genera automaticamente un salt casuale, itera 2^10 volte, e restituisce una stringa con salt e hash gia' embedded:$2y$10$x7kQ9mNp.... Quando poi faipassword_verify()obcrypt.compare(), non ricostruisci la password in chiaro — ricalcoli lo stesso hash con lo stesso salt estratto automaticamente dall'output e confronti. Mai usaremd5($password)ohash('sha256', $password)per le password: sono veloci per design, inutili contro Hashcat.
La detection di un attacco offline avviene PRIMA del cracking, non durante: il segnale e' l'esfiltrazione del DB (query anomala SELECT * FROM users nei log MySQL slow query, o traffico insolito verso l'esterno). Il cracking avviene su macchine dell'attaccante, senza toccare il tuo sistema. Monitorare l'exfiltration e' piu' efficace che monitorare i login.
Scenario Reale Blue Team#
Hashing e HMAC sono presenti in ogni livello dello stack — dai log di autenticazione ai webhook alle configurazioni di rete.
# Calcola hash SHA-256 di un file (verifica integrita' prima di eseguire)
sha256sum software_download.tar.gz
# Confronta con il checksum pubblicato sul sito ufficiale
# Identifica algoritmo hash da un digest sconosciuto (per incident response)
# MD5: 128 bit = 32 char hex
# SHA-1: 160 bit = 40 char hex
# SHA-256: 256 bit = 64 char hex
echo -n "482c811da5d5b4bc6d497ffa98491e38" | wc -c # 32 = MD5
# Verifica se un hash e' in un feed Threat Intelligence (IoC)
grep "482c811da5d5b4bc6d497ffa98491e38" /var/lib/suricata/rules/malware-hashes.txt
# Analizza costo hash bcrypt in un dump DB compromesso
# $2y$10$... → cost factor 10 → 2^10 = 1024 iterazioni
# $2y$12$... → cost factor 12 → 2^12 = 4096 iterazioni (piu' sicuro)
# Se vedi $1$ → MD5crypt (DEPRECATED, sostituire subito)
# Se vedi nessun $ e solo hex → hash in chiaro senza salt (CRITICO)
# Verifica HMAC di un webhook GitHub in bash
echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "$GITHUB_SECRET"
# Confronta con X-Hub-Signature-256 nell'header della richiestaDurante un incident response su un DB compromesso, se trovi hash in formato $apr1$ (MD5-APR, Apache) o $1$ (MD5crypt) — sono craccabili in ore. Se trovi hash esadecimali senza prefisso (MD5 puro) — sono craccabili in minuti. $2y$ (bcrypt) e' accettabile se il cost factor e' >= 10. Priorita' immediata: obbligare il reset delle password degli utenti colpiti.
Collegato a#
- crypto — categoria
- cryptography — fondamentali crittografici: hashing, simmetrica, asimmetrica
- asymmetric-encryption — firma digitale: si firma l'hash del documento, non il grezzo


