Downloads unter Linux mit sha256sum prüfen
Berechnen Sie mit sha256sum den Hash einer Datei und prüfen Sie ihn gegen SHA256SUMS. Ändern Sie ein Byte, um den sichtbaren Prüffehler zu beobachten.
Einen Download in zwei Minuten mit einer Prüfsumme verifizieren
Um einen Download mit einer Prüfsumme zu verifizieren, berechnen 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 diese 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 berechnet wurde. Sie sagt jedoch nichts darüber aus, wer den Digest erstellt hat. Für diese zweite Frage benötigen Sie eine Signatur und einen Schlüssel, dem Sie vertrauen. Der letzte Teil dieser Anleitung zeigt genau, wo die Grenze zwischen beiden Verfahren verläuft.
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 GNU coreutils, dem grundlegenden Befehlssatz, der auf jedem Ubuntu- oder Debian-Server vorhanden ist. 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 erzeugt immer dieselbe Ausgabe. Ändern Sie ein Zeichen der Datei und führen Sie den Befehl erneut aus. Der Digest ändert sich nicht nur geringfügig. Er sieht vollständig anders aus, weil das Ändern eines Eingabebits ungefähr die Hälfte der Ausgabebits ändert. Diese Eigenschaft macht eine Zeichenfolge mit 64 Zeichen zu einem brauchbaren Stellvertreter für ein 4-GB-Image.
Speichern Sie eine SHA256SUMS-Datei und prüfen Sie sie
Ein Digest auf dem Bildschirm ist am nächsten Tag wertlos. 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, bildet den Hash der in dieser Zeile angegebenen Datei und vergleicht die beiden Digests. Bei einem erfolgreichen Durchlauf wird für jede Datei eine Zeile ausgegeben:
payload.txt: OKPrüfen Sie zusätzlich den Exit-Status, da ein Skript diesen auswertet und den Text nicht liest. echo $? gibt nach einem erfolgreichen Durchlauf 0 aus. Der Name SHA256SUMS ist eine Konvention und keine zwingende Vorgabe. Distributionen und die meisten Release-Seiten verwenden ihn jedoch. Verwenden Sie ihn daher ebenfalls. So erkennt die nächste Person am Dateinamen, welchen Inhalt die Datei hat, ohne sie zu öffnen.
Ein Byte ändern und den Prüfvorgang fehlschlagen sehen
Beschädigen Sie die Datei nun absichtlich. Dadurch wird ein einzelnes Byte am Offset 5 geschrieben. Alles andere bleibt unverändert. Die Datei behält dadurch 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 dabei 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 Form der Beschädigung prüfen. Der Prüfvorgang 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 gespeicherten Digest übereinstimmt. Stellen Sie die ursprünglichen Bytes wieder her und bestätigen Sie, dass der Prüfvorgang wieder OK ergibt:
printf 'the payload of a totally ordinary download\n' > payload.txt
sha256sum -c SHA256SUMSDas ist der gesamte Ablauf. Bereits ein einzelnes 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 Ausgabezeile.
Wenn die Liste eine Datei nennt, die Sie nicht heruntergeladen haben
Eine echte SHA256SUMS-Datei einer Distribution enthält alle Images, die 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. Werden beide verwechselt, kostet das Zeit. FAILED bedeutet, dass die Bytes falsch sind. FAILED open or read bedeutet, dass sha256sum die Datei überhaupt nicht gefunden hat. Daher wurde nichts verglichen. Bei einem echten Download ist das Arbeitsverzeichnis die häufigste Ursache. Die Dateinamen in der Liste sind relativ zu dem Verzeichnis, in dem Sie den Befehl ausführen. Wechseln Sie in das Verzeichnis mit der Datei und führen Sie den Befehl erneut aus. Wenn Sie nur die tatsächlich vorhandenen Dateien prüfen möchten, verwenden Sie diese Option:
sha256sum --ignore-missing -c SHA256SUMS.allDer Befehl gibt payload.txt: OK aus und beendet sich mit Exit-Code 0. Wenn keiner der aufgeführten Dateinamen vorhanden ist, beendet sich --ignore-missing nicht stillschweigend erfolgreich bei null Dateien. Das Programm meldet no file was verified und beendet sich mit einem von 0 verschiedenen Exit-Code. Das ist das gewünschte Verhalten. Ein erfolgreicher Prüflauf, der nichts geprüft hat, wäre ein Fehler, den Sie sonst nicht bemerken würden.
Einen veröffentlichten Digest einfügen, ohne ihn mit dem Auge zu prüfen
Der Vergleich von 64 Hexadezimalzeichen mit dem Auge ist der Punkt, an dem diese Gewohnheit wirklich scheitert. Menschen prüfen die ersten vier und die letzten vier Zeichen und erklären die Werte dann 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 nur einen Digest enthält, ist keine Prüfsummenliste. Die Prüfung weist daher die gesamte Datei mit no properly formatted checksum lines found zurück, statt zu raten, welche Datei gemeint ist. Manche Projekte veröffentlichen stattdessen das mit BSD gekennzeichnete 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 selbst mit cat -A SHA256SUMS an. Der Befehl markiert das Ende jeder Zeile mit $ und zeigt Zeichen an, die sonst nicht sichtbar sind. Eine Zeile, die mit ^M$ endet, enthält möglicherweise einen von einem Windows-Editor übernommenen Wagenrücklauf. GNU sha256sum ignoriert dieses abschließende Zeichen und gibt weiterhin OK aus. Eine CRLF-Liste ist daher nicht die Ursache des Fehlers. Tools außerhalb von coreutils gehen damit jedoch weniger tolerant um. Normalisieren Sie die gespeicherte Kopie mit tr -d '\r' < SHA256SUMS > SHA256SUMS.clean.
Was weist eine Prüfsumme nach, und was nicht?
Eine Prüfsumme weist nur eines nach: Die Bytes auf Ihrer Festplatte entsprechen den Bytes, aus denen der veröffentlichte Digest erzeugt wurde. Damit wird versehentliche Beschädigung vollständig erkannt. Das gilt auch für einen unvorsichtigen Angreifer, der die Datei auf einem Download-Mirror ausgetauscht hat, aber keinen Zugriff auf die Seite hatte, auf der der Digest veröffentlicht wurde.
Die Prüfsumme sagt nichts über die Urheberschaft 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 beidem ändern kann, auch das andere ändern. Ihre OK-Zeile bedeutet dann nur, dass der Mirror mit sich selbst übereinstimmt. Daher gilt folgende Regel, die das Prüfen von Prüfsummen sinnvoll macht: Beziehen Sie den Digest von einer anderen Stelle als die Datei. Beispielsweise kann die Datei von einem Mirror oder über einen Torrent stammen, während Sie den Digest über die TLS-gesicherte (Transport Layer Security) eigene Domain des Projekts abrufen. Ein Angreifer muss dann zwei Stellen kontrollieren statt einer.
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: Seit 2004 lassen sich zwei verschiedene Dateien mit demselben MD5-Digest erzeugen, und 2020 wurde eine SHA-1-Kollision mit gewähltem Präfix veröffentlicht. Eine MD5SUMS-Datei erkennt weiterhin einen abgebrochenen Download, weil zufällige Beschädigung keine gezielt erzeugte Kollision ist. Sie kann jedoch niemanden daran hindern, Sie absichtlich zu täuschen. Wenn ein Projekt beide Varianten 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 die 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 Ihrer Festplatte mit der Liste. Die Vertrauenskette reicht damit vom Schlüssel bis zu den Bytes.
Der Schwachpunkt verlagert sich auf den Schlüssel. Wenn Sie den Schlüssel von derselben Seite abrufen, über die auch die Datei bereitgestellt wurde, geben Sie dem Angreifer beide Teile zurück. 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 erfordert dieselbe Sorgfalt wie ein privater SSH-Schlüssel, aus demselben Grund: Der Schlüssel ist die Vertrauensentscheidung. Alles Weitere übernimmt dieses Vertrauen.
Reproduzierbare Builds führen dieses Konzept einen Schritt weiter. Ein veröffentlichter Digest bindet Sie weiterhin an eine Binärdatei, die von einer einzelnen Maschine erstellt wurde. Wenn der Build eines Projekts reproduzierbar ist, kann jeder denselben Quellcode kompilieren und eine byte-identische Ausgabe erhalten. Unabhängige Builder können den veröffentlichten Digest dadurch bestätigen, statt sich auf die Aussage eines einzelnen Servers verlassen zu müssen. Das wird jedes Jahr wichtiger, weil immer mehr Code über automatisierte Pipelines und maschinell erstellte Patches eintrifft. Welche Inhalte Sie in einen Build übernehmen, ist eine Richtlinienfrage. Open-Source-Richtlinien für KI-gestützten Code behandeln dieselbe Lieferkette vom anderen Ende aus.
Ihr Paketmanager erledigt das bereits für Sie
Unter Debian und Ubuntu führt apt diese Prüfkette bei jeder Installation automatisch aus. Der Paketindex enthält für jede .deb-Datei einen SHA-256-Digest. Die Datei Release enthält die Digests dieser Indexdateien. 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 Prüfkette unterbrochen ist, meldet apt den Grund: 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. Das bedeutet normalerweise, dass ein Caching-Proxy eine veraltete Datei ausgeliefert hat oder dass Sie einen Mirror während der Synchronisierung erreicht haben.
Daran sollten Sie sich messen, wenn Sie auf der Startseite eines Projekts aufgefordert werden, ein Skript von curl direkt an eine Shell weiterzuleiten. Dabei werden die Bytes nicht geprüft, und Sie sehen ihren Inhalt nicht. Der Server kann einem Skript außerdem andere Inhalte 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. Dieser Ablauf kostet etwa zwanzig Sekunden. Es ist derselbe Ablauf, den Sie bei einem neuen VPS in den ersten zehn Minuten verwenden sollten, bevor Sie etwas anderes auf dem Server installieren.
Eine Prüfsummenliste für manuell installierte Dateien führen
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 Prüfsummenliste 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 daher, dass die Prüfung erfolgreich war, und echo $? bestätigt dies 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. Richten Sie dasselbe Muster mit sha256sum /usr/local/bin/* > ~/local-bin.sha256 auf echte Dateien und Sie haben eine Referenz. Die Pfade werden genau so in der Liste gespeichert, wie Sie sie eingegeben haben. Absolute Pfade stellen daher sicher, dass die Prüfung aus jedem Verzeichnis funktioniert.
Machen Sie sich klar, welchen Wert diese Referenz hat. Sie erkennt eine geänderte Datei. Sie erkennt keinen Angreifer, der bereits root hat, weil dieser Angreifer inventory.sha256 ebenso einfach überschreiben kann wie die Binärdatei. Bewahren Sie die Liste außerhalb des Systems auf, wenn sie Aussagekraft haben soll. Das gehört zur übergeordneten 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 der Angreifer die Seite kontrolliert, auf der der Digest veröffentlicht wurde, veröffentlicht er den Digest seiner eigenen Datei, und Ihre Prüfung gibt OK aus. Eine Übereinstimmung bestätigt die Konsistenz. Für eine Sicherheitsaussage benötigen Sie eine Signatur, die gegen einen Schlüssel geprüft wurde, den Sie aus einer anderen Quelle bezogen haben. Erst dann übernimmt der Digest dieses Vertrauensniveau.
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 Namen in einer SHA256SUMS-Datei sind relativ zu dem Verzeichnis, in dem Sie den Befehl ausführen. Wechseln Sie daher in das Verzeichnis mit dem Download und führen Sie den Befehl erneut aus. Wenn die Liste außerdem Dateien enthält, die Sie nicht heruntergeladen haben, fügen Sie --ignore-missing hinzu. Ein einfaches FAILED ohne open or read beschreibt die umgekehrte Situation: Die Datei wurde gelesen, aber ihr Digest stimmt nicht überein.
Ist MD5 zur Prüfung eines Downloads ausreichend?
Für die Erkennung zufälliger Beschädigungen: ja. Eine abgebrochene Übertragung oder ein fehlerhafter Festplattenblock erzeugt nicht zufällig einen übereinstimmenden MD5-Digest. Gegen einen Angreifer: nein. Seit 2004 lassen sich zwei unterschiedliche Dateien mit demselben MD5-Digest erzeugen. 2020 wurde außerdem eine Chosen-Prefix-Kollision für SHA-1 demonstriert. Verwenden Sie die SHA-256-Zeile, wenn ein Projekt beide Varianten veröffentlicht. Betrachten Sie ein Projekt, das ausschließlich MD5 verwendet, als Hinweis auf einen veralteten Release-Prozess.
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 Digest, der auf einer Webseite angezeigt wird?
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, das der Befehl ausgibt. Wenn Sie die Zeile mit printf '%s %s\n' erstellen, vermeiden Sie Formatierungsfehler, durch die sha256sum die Datei mit no properly formatted checksum lines found zurückweist.