Vai al contenuto
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

Cifratura, codifica e hashing: che cosa fa ciascuno

Distingui codifica, cifratura e hashing con laboratori su Base64, SHA-256 e OpenSSL. Impara perché Base64 non protegge niente e perché gli hash sono unidirezionali.

Base10 min di letturaDi NotHoly

Codifica, cifratura e hashing trasformano tutti e tre i dati in qualcos'altro, ed è per questo che la gente li confonde. Hanno obiettivi diversi. La codifica cambia il modo in cui i dati sono scritti, quindi chiunque può invertirla. La cifratura nasconde i dati a chi non ha una chiave, e con quella chiave la puoi invertire. L'hashing produce un'impronta breve che non puoi riportare all'input originale. Se vuoi ricordare una frase sola: Base64 non è cifratura, e un hash non nasconde niente quando l'input è corto.

Questo articolo separa le tre idee, poi ti chiede di eseguirle tutte e tre in un terminale sullo stesso testo. I risultati li confronti tu.

Da dove partire

Ti serve un terminale con base64, sha256sum e openssl. Su Windows 11 i comandi qui sotto girano in Git Bash, che arriva con Git for Windows. C'è anche una versione PowerShell del passo di hashing. Non servono conoscenze di crittografia, ma leggere prima l'articolo sul cifrario di Cesare aiuta a capire l'idea di chiave.

Puoi lanciare senza rischi ogni comando del laboratorio sulla tua macchina. Usa un file di prova e non un segreto vero.

Tre lavori diversi

Le tre operazioni rispondono a tre domande diverse.

Operazione Domanda a cui risponde Serve una chiave? È reversibile?
Codifica Come rappresento questi byte come testo o nel formato che un altro sistema si aspetta? No Sì, da chiunque
Cifratura Chi può leggere questi dati? Sì Sì, da chi ha la chiave giusta
Hashing Questi dati sono cambiati, o due valori coincidono? No No, per come è progettato

Tieni a mente questa tabella durante il laboratorio. Il resto dell'articolo spiega ogni riga.

La codifica cambia la rappresentazione

La codifica riscrive i dati in un'altra forma perché un sistema possa trasportarli. Base64 è l'esempio classico. Prende dei byte e li scrive usando 64 caratteri stampabili: da A a Z, da a a z, da 0 a 9, + e /, con = per il riempimento. Il formato è definito da RFC 4648. Gli allegati email, i data URL e molti payload delle API lo usano perché il mezzo di trasporto si aspetta del testo.

Base64 non ha segreti. La corrispondenza è pubblica e fissa. Qualsiasi strumento che conosca la regola può riportare l'output all'input. È lo scopo della codifica: far parlare i sistemi tra loro, senza alcuna pretesa di segretezza.

La cifratura nasconde i dati dietro una chiave

La cifratura prende dati leggibili, detti testo in chiaro, e con un algoritmo e una chiave li trasforma in testo cifrato. Chi non ha la chiave non dovrebbe ricavare niente di utile dal testo cifrato. Chi ha la chiave può decifrarlo.

Le famiglie sono due. La cifratura simmetrica usa la stessa chiave segreta per cifrare e decifrare. AES è la scelta comune. La cifratura asimmetrica usa una chiave pubblica e una privata. Questo articolo usa la cifratura simmetrica, come il comando OpenSSL del laboratorio.

Una buona cifratura dipende da più cose oltre all'algoritmo. Devi scegliere una modalità sicura, generare le chiavi con una buona fonte di casualità e proteggere la chiave. Il comando OpenSSL del laboratorio usa una password e PBKDF2 per derivare la chiave. Il testo di aiuto di OpenSSL dice che PBKDF2 usa 10.000 iterazioni per impostazione predefinita, a meno che tu non le cambi con -iter.

L'hashing crea un'impronta

Una funzione di hash crittografica prende un input di qualsiasi lunghezza e restituisce un output di lunghezza fissa. SHA-256 è specificato in FIPS 180-4, e il suo output è sempre di 256 bit, scritti come 64 caratteri esadecimali. Per chi comincia contano due proprietà:

  • Lo stesso input dà sempre lo stesso output.
  • Una piccola modifica all'input dovrebbe cambiare l'output al punto da farlo sembrare scollegato. Le buone funzioni di hash sono progettate in modo che trovare due input con lo stesso output sia impraticabile.

L'hashing è unidirezionale. Niente nell'output ti dice il testo originale. Puoi controllare se un input candidato produce un hash noto. Non puoi recuperare l'input dal solo hash, se non provando a indovinare e verificando.

Un hash è un'impronta e non un lucchetto. Chiunque può calcolare lo SHA-256 di un file pubblico. Un hash dimostra che due copie coincidono. Il file non lo nasconde.

Perché conta

La maggior parte degli errori di sicurezza reali in quest'area nasce dall'usare lo strumento sbagliato.

  • Uno sviluppatore salva una chiave API in Base64 e la chiama "cifrata". Chiunque veda il valore può decodificarlo con un comando.
  • Un team controlla un download con un hash, ma l'hash è pubblicato sulla stessa pagina del file, servita dallo stesso server compromesso. La verifica dimostra che il file corrisponde alla pagina e nient'altro.
  • Un'app web salva le password con SHA-256 semplice. Un database rubato si può attaccare in fretta con tentativi, perché SHA-256 è progettato per essere veloce. Le indicazioni di OWASP sulla conservazione crittografica dicono che le password vanno protette con algoritmi sicuri di hashing delle password invece che con una cifratura reversibile, e rimandano al Password Storage Cheat Sheet per i dettagli. Le scelte abituali sono hash lenti e con salt come Argon2id, scrypt, bcrypt o PBKDF2. Il prossimo articolo della serie tratta Argon2id.

Imparare presto la differenza ti evita queste trappole.

Laboratorio 1: codifica con Base64

Apri Git Bash in una cartella vuota. Codifica una frase breve, poi decodifica il risultato.

bash
echo -n 'hello lab' | base64

L'output che ho ottenuto su questa macchina con OpenSSL 3.2.4 e Git Bash:

text
aGVsbG8gbGFi

Ora decodifica quell'output:

bash
echo -n 'aGVsbG8gbGFi' | base64 -d

Output:

text
hello lab

Nota due cose. Primo, non c'è nessuna chiave. Secondo, echo -n conta. Senza -n, echo aggiunge un a capo e l'output Base64 cambia. Esegui echo 'hello lab' | base64 e confronta: io ho ottenuto aGVsbG8gbGFiCg==. Qui Base64 trasforma 9 byte in 12 caratteri, quindi l'output è più lungo dell'input.

Chiediti: qualcuno senza alcun segreto potrebbe invertire questa operazione? Sì. È il test che separa la codifica dalla cifratura.

Laboratorio 2: hashing con SHA-256

Passa la stessa frase a SHA-256:

bash
echo -n 'hello lab' | sha256sum

Output:

text
8fc6baba79a0d60b37dee612ccc1ec096ef52dba8cb0a24a6451e8bfb0e4d761 *-

Ora aggiungi un punto esclamativo e rieseguilo:

bash
echo -n 'hello lab!' | sha256sum

Output:

text
36902fb7fdea33458ad09dfeb52118dc47f99a8ca2b9001080366d55511de915 *-

I due hash non hanno nessuno schema visibile in comune. Un carattere ha cambiato tutto l'output. Sono entrambi di 64 caratteri esadecimali, cioè 256 bit.

Il - finale significa che l'input è arrivato dallo standard input e non da un file. Il * che lo precede è il marcatore di modalità binaria che stampa il sha256sum di Git Bash. Altri sistemi possono stampare due spazi, e l'hash è lo stesso. L'hash di un file funziona allo stesso modo.

Calcola l'hash di un file e rileva una modifica

Crea un piccolo file e calcolane l'hash:

bash
echo 'secret note' > note.txt
sha256sum note.txt

Sulla mia macchina, con terminazioni di riga Unix nel file, l'output è stato:

text
b5f891a5e064fec661025d0b0ec2de157487a6c2e5cc46dc0971fee56f86c645 *note.txt

Cambia il file, anche di un solo carattere, e ricalcola l'hash. Il valore sarà diverso. Le verifiche di integrità funzionano così. La verifica ti dice che il file è cambiato. Non ti dice che cosa è cambiato, e non impedisce a chi attacca di cambiare sia il file sia l'hash pubblicato.

Alternativa con Windows PowerShell

Se preferisci PowerShell, Windows ha un comando integrato:

powershell
Get-FileHash note.txt -Algorithm SHA256

Controlla nell'output la riga Hash, che mostra 64 caratteri esadecimali. L'hash dipende dai byte esatti del file. Il Set-Content di PowerShell scrive terminazioni di riga Windows (CRLF), diverse dalla terminazione LF dell'esempio Bash qui sopra. Sulla mia macchina, un file scritto così ha dato questo hash:

text
406A5646AE75CA75D032F306ABD33085DC9F656E3109BB962AEAB335EEC9ED85

Gli stessi byte passati a sha256sum in Git Bash hanno dato lo stesso valore in minuscolo. Se il tuo hash è diverso da quello dell'esempio Bash ma corrisponde al risultato PowerShell per il tuo file, il motivo sono le terminazioni di riga.

Laboratorio 3: cifrare un file con OpenSSL

Crea una nota e cifrala con AES-256-CBC. OpenSSL ti chiederà una password. Scegline una che ricorderai e che userai solo per questo laboratorio.

bash
echo 'secret note' > note.txt
openssl enc -aes-256-cbc -pbkdf2 -salt -in note.txt -out note.enc

OpenSSL chiede la password e il file cifrato viene scritto in note.enc. L'opzione -salt aggiunge un salt casuale, quindi cifrare due volte lo stesso file dà output diversi. Un file cifrato con -salt comincia con il testo ASCII Salted__. L'ho controllato sulla mia macchina. Il resto del file è binario e illeggibile.

Ora decifralo:

bash
openssl enc -d -aes-256-cbc -pbkdf2 -in note.enc

Inserisci la stessa password. Output:

text
secret note

La decifratura funziona solo con la password giusta. Ho provato con una sbagliata. OpenSSL ha stampato bad decrypt ed è uscito con un errore.

La cifratura da sola non rileva la manomissione

Adesso cambia un byte del file cifrato e prova a decifrarlo. Io ho invertito un bit dentro il blocco di testo cifrato di una copia chiamata tampered.enc. La decifratura è fallita con bad decrypt e il comando è uscito con stato 1.

Questo fallimento è un caso fortunato dovuto al padding di CBC. Altre modifiche possono produrre output senza senso e nessun errore. La lezione è che la cifratura semplice non ti dà un segnale affidabile del fatto che il testo cifrato sia stato modificato. I sistemi che hanno bisogno sia di segretezza sia di integrità usano la cifratura autenticata, come AES-GCM, o aggiungono un codice di autenticazione del messaggio. È un argomento avanzato, ma spiega perché un file cifrato non è automaticamente un file affidabile.

Le tre operazioni a confronto

Passa lo stesso testo a ciascuna operazione e confronta:

Operazione Comando Output su hello lab (osservato)
Codifica echo -n 'hello lab' | base64 aGVsbG8gbGFi
Hashing echo -n 'hello lab' | sha256sum 8fc6baba...e4d761
Cifratura openssl enc ... -in note.txt Dati binari, serve la password per leggerli

Chiediti che cosa ti permette di fare ciascun output:

  • Base64 permette a chiunque di recuperare hello lab.
  • L'hash ti permette di verificare che un input candidato sia hello lab, ma non di recuperare l'input dal solo hash.
  • Il file cifrato ti permette di recuperare secret note solo con la password.

Errori comuni

Chiamare Base64 "cifratura" o "offuscamento" per i segreti. Base64 non nasconde niente. Chiunque veda una stringa Base64 può decodificarla. Conserva i segreti in un secrets manager o in un archivio cifrato, mai in forma codificata.

Usare un hash come lucchetto. Un hash è unidirezionale, ma gli input corti o comuni si possono indovinare. Calcola l'hash di hello lab e chi attacca con un elenco di frasi comuni lo recupera senza rompere SHA-256. Per questo l'hashing delle password richiede salt e algoritmi lenti.

Usare SHA-256 semplice per le password. SHA-256 è veloce per progetto, il che va bene per i checksum dei file e male per la conservazione delle password. Usa una funzione di hashing delle password fatta apposta.

Fidarsi di un hash che viene dallo stesso posto del file. Un checksum sulla stessa pagina compromessa non dimostra niente. Ottieni l'hash atteso attraverso un canale separato e affidabile, o verifica una firma digitale.

Dimenticare che la cifratura richiede la gestione delle chiavi. Il laboratorio usa una password digitata a un prompt. I sistemi reali devono conservare, ruotare e proteggere le chiavi. Perdere la chiave vuol dire perdere i dati.

Scriversi la crittografia da soli. Usa librerie e protocolli consolidati. I comandi del laboratorio servono per imparare e non sono un modello per sistemi di produzione.

Per andare oltre

Ripeti i tre laboratori con una frase diversa, poi con un file di qualche kilobyte. Nota che l'output Base64 cresce di circa un terzo, l'hash resta di 64 caratteri e il file cifrato cresce solo per l'intestazione e il padding.

Poi leggi qualcosa sull'hashing delle password. Lì il problema è il costo dei tentativi, più che l'hashing in sé. Il prossimo articolo della serie, Come funziona l'hashing delle password con Argon2id, spiega i salt, i fattori di lavoro e perché contano gli hash lenti. Se prima vuoi un ripasso sul lato dei cifrari, leggi Cifrario di Cesare in Python. Mostra una chiave e un algoritmo in una forma che puoi provare.

Quando studi protocolli reali, cerca tre cose in ciascuno: che cosa codifica, che cosa cifra e di che cosa calcola l'hash. Gran parte della confusione sparisce quando ti chiedi quale dei tre lavori stia facendo ciascuna parte.

Fonti

Fonti

  1. RFC 4648: The Base16, Base32, and Base64 Data Encodings
  2. FIPS 180-4: Secure Hash Standard (SHS), with update 1
  3. OWASP Cryptographic Storage Cheat Sheet

Altro su Crittografia

Crittografia

Password e hashing con Argon2id

Perché gli hash veloci non vanno bene per le password, a cosa servono salt e work factor e come calcolare e verificare un hash con Argon2id in Python usando argon2-cffi.

Intermedio10 min di lettura