Downloads unter Linux mit SHA256-Prüfsummen prüfen
Erzeugen Sie mit sha256sum einen Hash, prüfen Sie ihn gegen SHA256SUMS und ändern Sie ein Byte. So sehen Sie den Fehler und die Grenze der Prüfsumme.
Einen Download in zwei Minuten mit einer Prüfsumme verifizieren
Um einen Download mit einer Prüfsumme zu verifizieren, bilden Sie den Hash der empfangenen Datei und lassen ein Tool diesen Hash mit dem vom Herausgeber angegebenen Hash vergleichen. sha256sum erledigt beide Teile: Ohne weitere Optionen gibt es einen Digest aus, und mit -c liest es eine Liste von Digests ein und meldet, welche Dateien übereinstimmen. In dieser Anleitung durchlaufen Sie den gesamten Ablauf mit einer selbst erstellten Datei. Anschließend beschädigen Sie die Datei absichtlich, damit Sie den Fehler direkt beobachten können, statt nur darüber zu lesen.
Behalten Sie während der gesamten Anleitung einen Satz im Hinterkopf. Eine Prüfsumme zeigt, ob die vorliegenden Bytes den Bytes entsprechen, aus denen der Digest erzeugt wurde. Sie zeigt nicht, wer diesen Digest erzeugt hat. Für diese zweite Frage benötigen Sie eine Signatur und einen vertrauenswürdigen Schlüssel. Der letzte Teil dieser Anleitung zeigt genau, wo die Grenze zwischen beiden Verfahren liegt.
Eine Datei zum Üben erstellen
Arbeiten Sie in einem temporären Verzeichnis, damit keiner der folgenden Befehle den übrigen Teil des Systems verändert. Jeder folgende Befehl stammt aus den GNU coreutils, dem grundlegenden Befehlssatz auf jedem Ubuntu- oder Debian-Server. Sie müssen daher nichts installieren.
mkdir -p ~/checksum-demo
cd ~/checksum-demo
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum payload.txtSie erhalten eine Zeile: 64 hexadezimale Zeichen, zwei Leerzeichen und anschließend den Dateinamen. Diese 64 Zeichen sind der Digest der Datei. Führen Sie den Befehl erneut aus. Die Zeile ist identisch, weil Hashing deterministisch ist: Dieselbe Eingabe liefert immer dieselbe Ausgabe. Ändern Sie ein Zeichen der Datei und führen Sie den Befehl erneut aus. Der Digest verändert sich nicht nur geringfügig. Er sieht vollständig anders aus, weil das Ändern eines Eingabebits etwa die Hälfte der Ausgabebits ändert. Diese Eigenschaft macht eine Zeichenfolge aus 64 Zeichen zu einem geeigneten Stellvertreter für ein 4-GB-Image.
Eine SHA256SUMS-Datei speichern und anschließend prüfen
Ein Digest auf dem Bildschirm ist einen Tag später nutzlos. Schreiben Sie ihn in eine Datei und verwenden Sie dabei das Format, das sha256sum selbst erzeugt. So kann das Tool die Datei später wieder einlesen.
sha256sum payload.txt > SHA256SUMS
cat SHA256SUMS
sha256sum -c SHA256SUMSsha256sum -c liest jede Zeile der Liste ein, bildet den Hash der in dieser Zeile genannten Datei und vergleicht die beiden Digests. Ein erfolgreicher Lauf gibt eine Zeile pro Datei aus:
payload.txt: OKPrüfen Sie außerdem den Exit-Status, weil ein Skript diesen auswertet und den Text nicht einliest. echo $? gibt nach einem erfolgreichen Lauf 0 aus. Der Name SHA256SUMS ist eine Konvention und keine Vorgabe. Distributionen und die meisten Release-Seiten verwenden ihn jedoch. Verwenden Sie ihn daher ebenfalls. So erkennt die nächste Person ohne Öffnen der Datei, welchen Inhalt sie enthält.
Ein Byte ändern und sehen, wie die Prüfung fehlschlägt
Beschädigen Sie die Datei nun absichtlich. Damit wird ein einzelnes Byte am Offset 5 überschrieben. Alles andere bleibt unverändert. Die Datei behält daher ihre Länge und ihren Namen.
printf 'X' | dd of=payload.txt bs=1 seek=5 conv=notrunc status=none
cat payload.txt
sha256sum -c SHA256SUMSconv=notrunc ist das entscheidende Flag: Ohne dieses Flag kürzt dd die Datei an der Stelle, an der der Schreibvorgang endet. Sie würden dann eine deutlich offensichtlichere Art von Beschädigung prüfen. Die Prüfung gibt nun Folgendes aus:
payload.txt: FAILED
sha256sum: WARNING: 1 computed checksum did NOT matchecho $? gibt 1 aus. FAILED bedeutet, dass die Datei gelesen wurde und ihr Digest nicht mit dem in der Liste hinterlegten Digest übereinstimmt. Stellen Sie die ursprünglichen Bytes wieder her und bestätigen Sie, dass die Prüfung wieder OK zurückgibt:
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMSDas ist der gesamte Ablauf. Bereits ein einziges abweichendes Byte an einer beliebigen Stelle der Datei führt zu FAILED. Ein Download, der wegen einer unterbrochenen Verbindung vorzeitig endet, ein Mirror, der den Build vom Vortag ausliefert, ein Proxy, der die Datei während der Übertragung verändert, oder ein Datenträger, der einen fehlerhaften Block zurückgibt: Alle diese Fälle führen zur selben Meldung.
Wenn die Liste eine Datei nennt, die Sie nicht heruntergeladen haben
Eine echte SHA256SUMS-Datei einer Distribution listet jedes Image auf, das das Projekt veröffentlicht, und Sie haben eines davon heruntergeladen. Stellen Sie diese Situation hier nach.
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 ist ein anderer Fehler als FAILED. Wenn Sie beide verwechseln, verlieren Sie Zeit. FAILED bedeutet, dass die Bytes nicht korrekt sind. FAILED open or read bedeutet, dass sha256sum die Datei überhaupt nicht gefunden hat und daher nichts verglichen wurde. Bei einem echten Download liegt die häufigste Ursache im Arbeitsverzeichnis, weil die Namen in der Liste relativ zu dem Verzeichnis sind, in dem Sie den Befehl ausführen. Wechseln Sie in das Verzeichnis, das die Datei enthält, und führen Sie den Befehl erneut aus. Wenn Sie nur die Dateien prüfen möchten, die tatsächlich vorhanden sind, verwenden Sie diesen Befehl:
sha256sum --ignore-missing -c SHA256SUMS.allDieser gibt payload.txt: OK aus und beendet sich mit dem Exit-Code 0. Wenn keiner der aufgelisteten Namen vorhanden ist, ist --ignore-missing bei null Dateien nicht stillschweigend erfolgreich. Das Programm meldet no file was verified und beendet sich mit einem Exit-Code ungleich null. Dieses Verhalten ist erwünscht, weil ein erfolgreicher Lauf, der nichts geprüft hat, der Fehler wäre, den Sie nie bemerken würden.
Veröffentlichten Digest einfügen, ohne ihn per Sichtprüfung zu vergleichen
Der Vergleich von 64 hexadezimalen Zeichen per Sichtprüfung ist der Punkt, an dem diese Gewohnheit wirklich versagt. Viele prüfen die ersten vier und die letzten vier Zeichen und erklären den Wert für identisch. Genau auf diesen Vergleich setzt ein entschlossener Angreifer. Überlassen Sie den Vergleich stattdessen dem Tool. Setzen Sie EXPECTED auf den Digest, den Sie vom Herausgeber kopiert haben. Verwenden Sie dazu EXPECTED= gefolgt vom eingefügten Wert. Erstellen Sie anschließend die einzelne Zeile, die -c erwartet:
printf '%s %s\n' "$EXPECTED" payload.txt > payload.sha256
cat payload.sha256
sha256sum -c payload.sha256Zwischen dem Digest und dem Dateinamen stehen zwei Leerzeichen. Deshalb enthält die Formatzeichenfolge zwei Leerzeichen. Das ist die Form, die sha256sum schreibt, und die Form, die -c einliest. Eine Datei, die ausschließlich einen Digest enthält, ist keine Prüfsummen-Zeile. Die Prüfung weist die gesamte Datei daher mit no properly formatted checksum lines found zurück, statt zu erraten, welche Datei gemeint ist. Einige Projekte veröffentlichen stattdessen das mit BSD markierte Format: SHA256 (payload.txt) = gefolgt vom Digest. GNU coreutils schreibt dieses Format mit sha256sum --tag payload.txt und liest es mit -c wieder ein. Sie können daher beide Formen speichern.
Wenn sich eine Prüfung ungewöhnlich verhält, sehen Sie sich die Liste mit cat -A SHA256SUMS selbst an. Der Befehl markiert das Ende jeder Zeile mit $ und zeigt Zeichen an, die sonst nicht sichtbar sind. Eine Zeile, die mit ^M$ endet, hat möglicherweise ein Wagenrücklaufzeichen aus einem Windows-Editor übernommen. GNU sha256sum ignoriert dieses nachgestellte Zeichen und gibt weiterhin OK aus. Eine CRLF-Liste ist daher nicht die Ursache des Problems, auch wenn Tools außerhalb von coreutils dabei weniger tolerant sind. Normalisieren Sie die gespeicherte Kopie mit tr -d '\r' < SHA256SUMS > SHA256SUMS.clean.
Was beweist eine Prüfsumme, und was beweist sie nicht?
Eine Prüfsumme beweist eine Sache: Die Bytes auf Ihrer Festplatte entsprechen den Bytes, aus denen der veröffentlichte Digest berechnet wurde. Damit wird versehentliche Beschädigung vollständig erkannt. Das gilt auch für einen nachlässigen Angreifer, der die Datei auf einem Download-Mirror ausgetauscht hat, aber keinen Zugriff auf die Seite hatte, auf der der Digest veröffentlicht wurde.
Über die Urheberschaft sagt sie nichts aus. Ein Digest ist eine Eigenschaft von Bytes, nicht von Personen. Wenn eine Seite sowohl die Datei als auch den Digest bereitstellt, kann jeder, der eines von beiden ändern kann, auch das andere ändern. Ihre OK-Zeile bedeutet dann nur, dass der Mirror mit sich selbst übereinstimmt. Deshalb gilt folgende Regel, die Prüfsummen sinnvoll macht: Beziehen Sie den Digest von einer anderen Stelle als die Datei. Beispielsweise können Sie den Digest von der Domain des Projekts über TLS (Transport Layer Security) beziehen, während das Image von einem Mirror oder über einen Torrent stammt. Dann müsste ein Angreifer zwei Stellen kontrollieren statt einer. Außerdem sagt eine Prüfsumme nichts darüber aus, was die verifizierten Bytes ausführen, sobald Sie sie starten. Das ist eine separate Frage, die Sie sich bei allem stellen sollten, was in Ihrem Auftrag ausgeführt wird, vom Installationsskript bis zu einem dsh-Plugin, das mit den Berechtigungen Ihres Agents ausgeführt wird.
Auch der Algorithmus ist wichtig. Für SHA-256 (Secure Hash Algorithm, 256-Bit-Ausgabe) ist bis August 2026 keine Kollision bekannt. Deshalb verwenden Herausgeber diesen Algorithmus. MD5 (Message Digest 5) und SHA-1 sind nicht ausreichend: Zwei verschiedene Dateien mit demselben MD5-Digest lassen sich seit 2004 erzeugen, und eine SHA-1-Kollision mit gewähltem Präfix wurde 2020 veröffentlicht. Eine MD5SUMS-Datei erkennt trotzdem einen abgebrochenen Download, weil zufällige Beschädigungen keine gezielt erzeugte Kollision darstellen. Sie kann jedoch niemanden davon abhalten, Sie zu täuschen. Wenn ein Projekt beide veröffentlicht, verwenden Sie die SHA-256-Zeile.
Wenn Signaturen übernehmen
Eine Signatur schließt die Lücke, die ein Digest offenlässt. Der Herausgeber signiert die Digest-Datei mit einem privaten Schlüssel, und Sie prüfen sie mit dem zugehörigen öffentlichen Schlüssel: gpg --verify SHA256SUMS.asc SHA256SUMS. Wenn diese Prüfung erfolgreich ist, stammt die Liste der Digests von der Person oder Organisation, die diesen Schlüssel besitzt. Anschließend verknüpft sha256sum -c SHA256SUMS die Datei auf Ihrem Datenträger mit der Liste. Die Vertrauenskette reicht damit vom Schlüssel bis zu den Bytes.
Die Schwachstelle verlagert sich auf den Schlüssel. Wenn Sie den Schlüssel von derselben Seite abrufen, von der auch die Datei stammt, übergeben Sie dem Angreifer beide Teile. GnuPG weist darauf hin: Bei einer ersten Prüfung werden Good signature und WARNING: This key is not certified with a trusted signature! ausgegeben. Good signature bedeutet, dass die mathematische Prüfung erfolgreich ist. Es bedeutet nicht, dass der Schlüssel zu dem von Ihnen erwarteten Projekt gehört. Rufen Sie den Fingerabdruck aus einer zweiten Quelle ab, beispielsweise aus der Dokumentation des Projekts auf einer anderen Domain oder aus einem Distributionspaket, das den Schlüssel bereits enthält. Vergleichen Sie den vollständigen Fingerabdruck und nicht nur die letzten acht Zeichen. Das ist dieselbe Sorgfalt, die ein privater SSH-Schlüssel verdient, und zwar aus demselben Grund: Der Schlüssel ist die Vertrauensentscheidung. Alles Weitere übernimmt diese Entscheidung.
Reproduzierbare Builds führen diesen Gedanken einen Schritt weiter. Ein veröffentlichter Digest bindet Sie weiterhin an eine Binärdatei, die von einer bestimmten Maschine erstellt wurde. Wenn der Build eines Projekts reproduzierbar ist, kann jeder denselben Quellcode kompilieren und eine byte-identische Ausgabe erzeugen. Unabhängige Builder können den veröffentlichten Digest dann bestätigen, statt darauf zu vertrauen, dass ein einzelner Server die richtige Datei geliefert hat. Das wird jedes Jahr wichtiger, weil immer mehr Code über automatisierte Pipelines und von Maschinen erstellte Patches in Projekte gelangt. Die Entscheidung, was Sie in einen Build aufnehmen, ist eine Richtlinienfrage. Open-Source-Richtlinien für KI-gestützten Code betrachten dieselbe Software-Lieferkette vom anderen Ende aus.
Das erledigt Ihr Paketmanager bereits für Sie
Unter Debian und Ubuntu führt apt diese Prüfungskette bei jeder Installation ohne Rückfrage aus. Der Paketindex enthält für jede .deb-Datei einen SHA-256-Hash. Die Datei Release enthält die Hashes dieser Indexdateien, und InRelease enthält eine Signatur über Release. Diese wird anhand der Schlüssel in /usr/share/keyrings und /etc/apt/trusted.gpg.d geprüft. Wenn die Kette unterbrochen ist, meldet apt dies: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY, wenn der Schlüssel eines Drittanbieter-Repositorys fehlt, oder Hash Sum mismatch, wenn der abgerufene Index nicht mit dem signierten Release übereinstimmt. In der Regel hat dann ein Caching-Proxy eine veraltete Datei ausgeliefert, oder Sie haben einen Mirror während der Synchronisierung erreicht.
An diesem Standard sollten Sie sich orientieren, wenn die Startseite eines Projekts empfiehlt, ein Skript von curl direkt in eine Shell zu pipen. Dabei werden die Bytes nicht verifiziert, und Sie sehen sie nie. Der Server kann einem Skript außerdem einen anderen Inhalt liefern als einem Browser. Danach haben Sie keine Kopie zur Prüfung. Laden Sie die Datei mit curl -fsSL <url> -o install.sh herunter, hashen Sie sie, lesen Sie sie mit less und führen Sie sie erst danach aus. Diese Gewohnheit kostet etwa zwanzig Sekunden. Sie ist auch auf einem neuen VPS in den ersten zehn Minuten sinnvoll, bevor Sie irgendetwas anderes auf dem Server installieren.
Liste Prüfsummen für manuell installierte Dateien
Von apt installierte Pakete werden erfasst. Eine Binärdatei, die Sie nach /usr/local/bin kopiert haben, wird nicht erfasst, und kein Prozess auf dem System überwacht sie. Eine Liste mit Prüfsummen macht daraus eine Prüfung, die Sie bei Bedarf ausführen können:
printf 'a second file\n' > notes.txt
sha256sum *.txt > inventory.sha256
sha256sum -c --quiet inventory.sha256--quiet gibt nichts aus, wenn alle Dateien übereinstimmen. Wenn einige Dateien nicht übereinstimmen, werden nur die fehlgeschlagenen Zeilen ausgegeben. Keine Ausgabe bedeutet also, dass die Prüfung bestanden wurde, und echo $? bestätigt das mit 0. Diese Form eignet sich für einen geplanten Job. --status geht noch weiter und gibt überhaupt nichts aus. Ihnen bleibt dann nur der Exit-Status. Wenden Sie dasselbe Muster mit sha256sum /usr/local/bin/* > ~/local-bin.sha256 auf echte Dateien an, erhalten Sie eine Baseline. Pfade werden genau so in der Liste gespeichert, wie Sie sie eingegeben haben. Absolute Pfade sorgen daher dafür, dass die Prüfung aus jedem Verzeichnis funktioniert.
Seien Sie sich darüber im Klaren, welchen Wert diese Baseline hat. Sie erkennt eine geänderte Datei. Sie erkennt jedoch keinen Angreifer, der bereits root besitzt, weil dieser Angreifer inventory.sha256 genauso einfach überschreiben kann wie zuvor die Binärdatei. Bewahren Sie die Liste außerhalb des Rechners auf, wenn sie aussagekräftig bleiben soll. Das gehört zur umfassenderen Frage, wie sehr Sie einem VPS tatsächlich vertrauen, und wer sonst auf den darunterliegenden Datenträger zugreifen kann.
FAQ
Bedeutet eine übereinstimmende Prüfsumme, dass der Download sicher ist?
Nein. Das bedeutet, dass die vorhandenen Bytes mit dem verglichenen Digest übereinstimmen. Wenn ein Angreifer die Seite kontrolliert, auf der der Digest veröffentlicht wurde, kann er den Digest seiner eigenen Datei veröffentlichen, und Ihre Prüfung gibt OK aus. Eine Übereinstimmung bestätigt die Konsistenz. Eine Sicherheitsprüfung erfordert eine Signatur, die gegen einen Schlüssel verifiziert wurde, den Sie aus einer anderen Quelle bezogen haben. Erst dann übernimmt der Digest dieses Vertrauen.
Warum gibt sha256sum -c FAILED open or read aus?
Weil der Befehl die Datei nicht gelesen hat. Eine separate Zeile direkt darüber enthält mit No such file or directory den Namen, nach dem gesucht wurde. Die Dateinamen in einer SHA256SUMS-Datei sind relativ zu dem Verzeichnis, in dem Sie den Befehl ausführen. Wechseln Sie daher in das Verzeichnis, das den Download enthält, und führen Sie den Befehl erneut aus. Wenn die Liste auch Dateien enthält, die Sie nicht heruntergeladen haben, fügen Sie --ignore-missing hinzu. Ein einfaches FAILED ohne open or read bezeichnet die umgekehrte Situation: Die Datei wurde gelesen, aber ihr Digest stimmt nicht überein.
Ist MD5 zur Überprüfung eines Downloads ausreichend?
Für die Erkennung versehentlicher Beschädigungen: ja. Eine unvollständige Übertragung oder ein fehlerhafter Datenträgerblock erzeugt nicht zufällig einen übereinstimmenden MD5-Digest. Gegen einen Angreifer: nein. Seit 2004 lassen sich zwei verschiedene Dateien mit demselben MD5-Digest erzeugen. 2020 wurde außerdem eine Chosen-Prefix-Kollision für SHA-1 nachgewiesen. Verwenden Sie die SHA-256-Zeile, wenn ein Projekt beide Varianten veröffentlicht. Ein Projekt, das ausschließlich MD5 verwendet, weist auf einen veralteten Release-Prozess hin.
Was ist der Unterschied zwischen sha256sum -c und gpg --verify?
sha256sum -c weist nach, dass eine Datei mit einem Digest übereinstimmt. gpg --verify weist nach, dass eine Digest-Datei vom Inhaber eines bestimmten privaten Schlüssels signiert wurde. Die beiden Prüfungen beantworten unterschiedliche Fragen. Führen Sie daher beide aus, wenn ein Projekt beide anbietet. Die Signatur macht die Digest-Liste vertrauenswürdig. Die Digest-Liste macht anschließend die heruntergeladene Datei vertrauenswürdig.
Wie prüfe ich eine Datei gegen einen auf einer Webseite angezeigten Digest?
Vergleichen Sie die Zeichen nicht manuell. Speichern Sie den Digest und den Dateinamen in einer einzigen Zeile, getrennt durch zwei Leerzeichen. Führen Sie anschließend sha256sum -c für diese Datei aus und lesen Sie OK oder FAILED aus, das der Befehl ausgibt. Wenn Sie die Zeile mit printf '%s %s\n' erstellen, vermeiden Sie Formatierungsfehler, aufgrund derer sha256sum die Datei mit no properly formatted checksum lines found zurückweist.