Come verificare un download con sha256sum su Linux
Usa sha256sum per confrontare un file con SHA256SUMS, poi modifica un byte e osserva il controllo fallire: capirai cosa dimostra davvero un checksum.
Verificare un download con un checksum in due minuti
Per verificare un download con un checksum, calcola l’hash del file ricevuto e lascia che uno strumento confronti questo hash con quello pubblicato dal fornitore. sha256sum esegue entrambe le operazioni: senza opzioni stampa un digest, mentre con -c legge un elenco di digest e segnala quali file corrispondono. Questa guida esegue l’intero processo su un file creato da te, quindi modifica intenzionalmente quel file per mostrarti il rilevamento dell’errore invece di limitarsi a descriverlo.
Tieni presente una frase per tutta la procedura. Un checksum indica se i byte in tuo possesso sono quelli da cui è stato prodotto il digest, ma non dice nulla sull’identità di chi lo ha prodotto. Per rispondere a questa seconda domanda servono una firma e una chiave di cui ti fidi. L’ultima parte di questa guida mostra esattamente dove passa il confine tra i due concetti.
Crea un file su cui fare pratica
Lavora in una directory temporanea, in modo che nessuna operazione eseguita in questa sezione modifichi il resto del sistema. Tutti i comandi riportati di seguito provengono da GNU coreutils, il set di comandi di base presente su qualsiasi server Ubuntu o Debian; non è quindi necessario installare nulla.
mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txtOttieni una riga composta da 64 caratteri esadecimali, due spazi e il nome del file. I 64 caratteri costituiscono il digest del file. Se esegui di nuovo il comando, la riga è identica, perché l'hashing è deterministico: lo stesso input produce sempre lo stesso output. Modifica un carattere del file ed esegui di nuovo il comando: il digest non cambia soltanto di poco. Ha un aspetto completamente diverso, perché l'inversione di un singolo bit dell'input inverte circa la metà dei bit dell'output. Questa proprietà rende una stringa di 64 caratteri un sostituto utilizzabile per un'immagine da 4 GB.
Salvare un file SHA256SUMS, quindi verificarlo
Un digest visualizzato sullo schermo non è utile il giorno successivo. Scrivilo in un file, nel formato prodotto da sha256sum, in modo che lo strumento possa rileggerlo in seguito.
sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMSsha256sum -c legge ogni riga dell’elenco, calcola l’hash del file indicato nella riga e confronta i due digest. Un’esecuzione corretta stampa una riga per ogni file:
payload.txt: OKControlla anche lo stato di uscita, perché uno script legge quello e non il testo. echo $? stampa 0 dopo un’esecuzione corretta. Il nome SHA256SUMS è una convenzione, non una regola, ma le distribuzioni e la maggior parte delle pagine delle release lo usano. Usalo anche tu: chi leggerà il file in seguito saprà cosa contiene senza doverlo aprire.
Modificare un byte e osservare il fallimento del controllo
Ora danneggiare intenzionalmente il file. Questo comando scrive un solo byte all'offset 5 e lascia invariato tutto il resto, quindi il file mantiene lunghezza e nome.
printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMSconv=notrunc è il flag importante: senza di esso, dd tronca il file nel punto in cui interrompe la scrittura e si verifica un tipo di danneggiamento molto più evidente. Ora il controllo mostra:
payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT matchecho $? mostra 1. FAILED indica che il file è stato letto e che il digest non corrisponde a quello presente nell'elenco. Ripristinare i byte originali e verificare che il controllo restituisca OK:
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMSQuesta è l'intera procedura. Una differenza di un solo byte, in qualsiasi punto del file, produce FAILED. Un download interrotto da una connessione caduta, un mirror che distribuisce la build del giorno precedente, un proxy che modifica il file durante il trasferimento o un disco che restituisce un blocco danneggiato: tutti questi casi producono la stessa riga.
Quando l’elenco indica un file che non hai scaricato
Un file SHA256SUMS reale di una distribuzione elenca tutte le immagini rilasciate dal progetto, mentre tu ne hai scaricata una sola. Riproduci qui questa situazione.
printf 'a second file\n' > notes.txt
sha256sum payload.txt notes.txt > SHA256SUMS.all
rm notes.txt
sha256sum -c SHA256SUMS.allpayload.txt: OK
sha256sum: notes.txt: No such file or directory
notes.txt: FAILED open or read
sha256sum: WARNING: 1 listed file could not be readFAILED open or read indica un errore diverso da FAILED e confondere i due casi fa perdere tempo. FAILED significa che i byte non sono corretti. FAILED open or read significa che sha256sum non ha trovato affatto il file, quindi non è stato eseguito alcun confronto. In un download reale, la causa più comune è la directory di lavoro, perché i nomi nell’elenco sono relativi alla directory da cui esegui il comando. Spostati nella directory che contiene il file ed esegui nuovamente il comando. Per controllare soltanto i file effettivamente presenti, usa questo comando:
sha256sum --ignore-missing -c SHA256SUMS.allIl comando stampa payload.txt: OK e termina con codice 0. Se nessuno dei nomi elencati è presente, --ignore-missing non termina correttamente quando deve controllare zero file. Segnala invece che no file was verified e termina con un codice diverso da zero. È il comportamento corretto, perché un controllo superato senza verificare alcun file è l’errore che non noteresti mai.
Incollare un digest pubblicato senza leggerlo a occhio
Confrontare a occhio 64 caratteri esadecimali è il punto in cui questa abitudine fallisce davvero. Si controllano i primi quattro caratteri e gli ultimi quattro, poi si considera il valore verificato. È esattamente il confronto su cui fa affidamento un attaccante determinato. Lasciate invece il confronto allo strumento. Impostate EXPECTED sul digest copiato dal publisher usando EXPECTED= seguito dal valore incollato, quindi create l'unica riga prevista da -c:
printf '%s %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256Tra il digest e il nome del file ci sono due spazi. Per questo la stringa di formato ne contiene due. Questa è la struttura prodotta da sha256sum e interpretata da -c. Un file che contiene soltanto un digest non è una riga di checksum. Per questo il controllo rifiuta l'intero file con no properly formatted checksum lines found invece di tentare di indovinare a quale file vi riferite. Alcuni progetti pubblicano invece lo stile con etichetta BSD, SHA256 (payload.txt) = seguito dal digest. GNU coreutils scrive questo formato con sha256sum --tag payload.txt e lo legge nuovamente con -c. Potete quindi salvare uno dei due formati.
Quando un controllo si comporta in modo anomalo, esaminate direttamente l'elenco con cat -A SHA256SUMS. Questo comando contrassegna la fine di ogni riga con $ e mostra i caratteri che altrimenti non sarebbero visibili. Una riga che termina con ^M$ ha acquisito un carattere carriage return da un editor Windows. GNU sha256sum ignora questo carattere finale e stampa comunque OK. Un elenco CRLF non è quindi la causa del problema, anche se gli strumenti esterni a coreutils gestiscono questo formato in modo meno tollerante. Normalizzate la copia conservata con tr -d '\r' < SHA256SUMS > SHA256SUMS.clean.
Che cosa dimostra un checksum e che cosa non dimostra?
Un checksum dimostra una sola cosa: i byte presenti sul disco sono i byte da cui è stato calcolato il digest pubblicato. Questo rileva completamente i danni accidentali. Rileva anche l'azione di un attaccante poco attento che ha sostituito il file su un mirror di download, ma non ha potuto modificare la pagina che pubblicava il digest.
Non dimostra nulla sull'autore. Un digest è un dato relativo ai byte, non alle persone. Se una pagina distribuisce sia il file sia il digest, chiunque possa modificare l'uno può modificare anche l'altro, e la riga OK indica soltanto che il mirror è coerente con se stesso. La regola che rende utile il controllo dei checksum è quindi questa: ottenere il digest da una fonte diversa da quella da cui si è ottenuto il file. Per esempio, il dominio del progetto tramite TLS (transport layer security), mentre l'immagine proviene da un mirror o da un torrent. In questo modo un attaccante deve controllare due punti invece di uno. Il checksum non dice inoltre nulla su ciò che quei byte verificati faranno una volta eseguiti. È una domanda separata, da porsi per qualunque elemento venga eseguito con i propri privilegi, da uno script di installazione a un plugin dsh eseguito con i privilegi del proprio agent.
Conta anche l'algoritmo. SHA-256 (secure hash algorithm, output a 256 bit) non presenta collisioni note ad agosto 2026, motivo per cui i publisher lo utilizzano. MD5 (message digest 5) e SHA-1 non sono più affidabili: dal 2004 è possibile costruire due file diversi con lo stesso digest MD5 e nel 2020 è stata pubblicata una collisione SHA-1 con prefisso scelto. Un file MD5SUMS rileva comunque un download troncato, perché una corruzione casuale non è una collisione costruita. Non può impedire a qualcuno di tentare di ingannare l'utente. Quando un progetto pubblica entrambi, utilizzare la riga SHA-256.
Quando le firme diventano necessarie
Una firma colma la lacuna lasciata aperta da un digest. Il publisher firma il file dei digest con una chiave privata e tu lo verifichi con la relativa chiave pubblica: gpg --verify SHA256SUMS.asc SHA256SUMS. Se la verifica riesce, l'elenco dei digest proviene da chi possiede quella chiave. Poi sha256sum -c SHA256SUMS collega il file presente sul disco all'elenco, completando la catena dalla chiave fino ai byte.
Il punto debole si sposta sulla chiave. Scaricare la chiave dalla stessa pagina che ha fornito il file consegna entrambe le parti all'attaccante. GnuPG lo segnala chiaramente: la prima verifica mostra Good signature insieme a WARNING: This key is not certified with a trusted signature!. Good signature significa che la verifica matematica è corretta. Non significa che la chiave appartenga al progetto a cui stai pensando. Recupera l'impronta digitale da una seconda fonte, ad esempio dalla documentazione del progetto pubblicata su un dominio diverso oppure da un pacchetto della distribuzione che include già la chiave, e confronta l'impronta completa invece degli ultimi otto caratteri. Questa è la stessa attenzione che richiede una chiave privata SSH, per lo stesso motivo: la chiave determina la fiducia e tutto ciò che ne dipende eredita quella fiducia.
Le build riproducibili portano questa idea un passo oltre. Un digest pubblicato ti vincola comunque a un binario compilato da una sola macchina. Quando la build di un progetto è riproducibile, chiunque può compilare lo stesso codice sorgente e ottenere un output identico a livello di byte. In questo modo, builder indipendenti possono confermare il digest pubblicato, invece di chiederti di fidarti di un singolo server. Questo è sempre più importante, perché ogni anno una quantità maggiore di codice arriva tramite pipeline automatizzate e patch scritte da macchine. Decidere quali componenti accettare in una build è una questione di policy, e le policy open source per il codice assistito dall'AI intervengono sulla stessa catena di fornitura, ma dall'estremità opposta.
Il gestore dei pacchetti lo fa già per te
Su Debian e Ubuntu, apt esegue questa catena a ogni installazione, senza richiedere interventi. L'indice dei pacchetti contiene un digest SHA-256 per ogni file .deb. Il file Release contiene i digest di questi file di indice, mentre InRelease contiene una firma su Release, verificata rispetto alle chiavi presenti in /usr/share/keyrings e /etc/apt/trusted.gpg.d. Quando la catena non è valida, apt lo segnala: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY quando manca la chiave di un repository di terze parti, oppure Hash Sum mismatch quando l'indice scaricato non corrisponde a Release firmato. Di solito significa che un proxy di caching ha fornito un file obsoleto oppure che il mirror era nel corso della sincronizzazione.
Questo è lo standard di riferimento quando la home page di un progetto indica di inoltrare uno script da curl direttamente a una shell tramite pipe. In questo modo non viene verificato nulla e non puoi vedere il contenuto dello script. Inoltre, il server può restituire un contenuto a uno script e un contenuto diverso a un browser, senza lasciarti una copia da controllare in seguito. Scarica il file con curl -fsSL <url> -o install.sh, calcolane l'hash, leggilo con less ed eseguilo solo dopo. Questa procedura richiede circa venti secondi ed è la stessa abitudine che conviene adottare su un VPS appena creato nei suoi primi dieci minuti, prima di installare qualsiasi altra cosa sul server.
Mantieni un elenco dei digest per ciò che installi manualmente
I pacchetti installati da apt vengono tracciati. Un binario copiato in /usr/local/bin non viene tracciato e nessun componente del sistema ne controlla l'integrità. Un elenco di digest consente di verificare questi file quando necessario:
printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256--quiet non stampa nulla quando tutti i file corrispondono e stampa solo le righe che non superano il controllo quando alcuni file differiscono. Quindi, l'assenza di output indica che il controllo è riuscito e echo $? lo conferma con 0. Questo è il formato da usare in un job pianificato. --status va oltre e non stampa nulla, lasciando disponibile soltanto il codice di uscita. Applica lo stesso schema a file reali con sha256sum /usr/local/bin/* > ~/local-bin.sha256 per creare una baseline. I percorsi vengono memorizzati nell'elenco esattamente come li hai digitati, quindi i percorsi assoluti consentono di eseguire il controllo da qualsiasi directory.
È importante definire correttamente il valore di questa baseline. Rileva un file modificato. Non rileva un attaccante che dispone già dell'accesso root, perché può riscrivere inventory.sha256 con la stessa facilità con cui ha riscritto il binario. Se vuoi che l'elenco abbia un valore effettivo, conservalo al di fuori della macchina. Questo rientra nella questione più ampia di quanto ti fidi realmente di un VPS e di chi altro può accedere al disco sottostante.
FAQ
Un checksum corrispondente indica che il download è sicuro?
No. Indica che i byte disponibili corrispondono al digest con cui li hai confrontati. Se l'attaccante controlla la pagina che pubblica il digest, pubblica il digest del proprio file e il controllo restituisce OK. Una corrispondenza dimostra la coerenza dei dati. Per dimostrare la sicurezza serve una firma verificata rispetto a una chiave ottenuta da una fonte diversa. Solo a quel punto il digest eredita quella attendibilità.
Perché sha256sum -c restituisce FAILED open or read?
Perché non ha letto il file. La riga immediatamente precedente indica No such file or directory con il nome che il comando stava cercando. I nomi contenuti in un file SHA256SUMS sono relativi alla directory da cui esegui il comando. Spostati quindi nella directory che contiene il download ed esegui di nuovo il comando. Se l'elenco include anche file che non hai scaricato, aggiungi --ignore-missing. Un semplice FAILED senza open or read indica la situazione opposta: il file è stato letto, ma il suo digest non corrispondeva.
MD5 è sufficiente per verificare un download?
Per rilevare danni accidentali, sì. Un trasferimento troncato o un blocco danneggiato del disco non produrrà casualmente un digest MD5 corrispondente. Contro un attaccante, no. È possibile costruire due file diversi con lo stesso digest MD5 dal 2004, mentre SHA-1 è stato compromesso da una collisione a prefisso scelto nel 2020. Usa la riga SHA-256 quando un progetto pubblica entrambi i digest e considera un progetto che usa solo MD5 come indicatore di un processo di rilascio obsoleto.
Qual è la differenza tra sha256sum -c e gpg --verify?
sha256sum -c dimostra che un file corrisponde a un digest. gpg --verify dimostra che un file di digest è stato firmato dal titolare di una determinata chiave privata. Rispondono a domande diverse, quindi eseguili entrambi quando il progetto li rende disponibili. La firma rende attendibile l'elenco dei digest, che a sua volta rende attendibile il file scaricato.
Come posso verificare un file rispetto a un digest pubblicato su una pagina web?
Non confrontare i caratteri a vista. Salva il digest e il nome del file su una singola riga, separati da due spazi, quindi esegui sha256sum -c sul file e leggi OK o FAILED nell'output. Creare la riga con printf '%s %s\n' evita gli errori di formattazione che fanno sì che sha256sum rifiuti il file con no properly formatted checksum lines found.