HOWTO · Python
Python-Prüfsumme
In diesem Tutorial erfahren Sie, wie Sie mit hashlib eine Datei-Prüfsumme berechnen und sie mit einem vertrauenswürdigen SHA-256-Digest vergleichen.
Auf dieser Seite
Eine Datei-Prüfsumme ist ein kompakter Digest, der aus den Bytes der Datei berechnet wird. Sie können ihn nach dem Herunterladen einer Datei berechnen und mit einem Digest vergleichen, der über einen vertrauenswürdigen Kanal veröffentlicht wurde. Eine Übereinstimmung hilft, versehentliche Änderungen oder Beschädigungen zu erkennen, beweist für sich allein aber nicht, wer die Datei erstellt hat: Ein Angreifer, der sowohl die Datei als auch ihren Referenz-Digest ersetzen kann, kann beide zur Übereinstimmung bringen.
Das Python-Modul hashlib stellt standardisierte Hash-Algorithmen bereit. Das Verfahren ist deterministisch: Dieselben Bytes und derselbe Algorithmus ergeben denselben Digest; eine Änderung auch nur eines Bytes verändert normalerweise das Ergebnis. Eine Prüfsumme beschreibt die Bytes, nicht den Dateinamen oder das Dateiformat.
Was eine Datei-Prüfsumme aussagt
Mit einer Prüfsumme können Sie prüfen, ob eine Kopie noch den erwarteten Inhalt hat. Der erwartete Wert muss aus einer Quelle stammen, der Sie vertrauen, etwa von einer separat authentifizierten Release-Seite. Zwei Werte zu vergleichen, die vom selben nicht vertrauenswürdigen Ort heruntergeladen wurden, bietet kaum Sicherheit. Verwenden Sie für Sicherheitsentscheidungen einen modernen kryptografischen Hash wie SHA-256 und überprüfen Sie die Quelle des Referenzwerts unabhängig davon.
Eine Prüfsumme mit hashlib berechnen
Öffnen Sie eine Datei im Binärmodus, damit Python ihre exakten Bytes hasht, ohne sie als Text zu dekodieren oder Zeilenenden umzuwandeln. Lesen Sie die Datei blockweise und übergeben Sie jeden Block an die Methode update() des Hash-Objekts. So bleibt der Speicherbedarf begrenzt, selbst wenn die Datei deutlich größer als der verfügbare Arbeitsspeicher ist. hexdigest() gibt den Digest als lesbaren Hexadezimaltext zurück; digest() liefert denselben Digest als gepackte Bytes.
Führen Sie dieses Beispiel aus. Die im Beispiel ausgegebenen Bezeichnungen bleiben auf Englisch, da der Code und die Ausgabe unverändert bleiben.
import hashlib
from pathlib import Path
from tempfile import TemporaryDirectory
def sha256_file(path):
digest = hashlib.sha256()
with open(path, "rb") as file:
for chunk in iter(lambda: file.read(64 * 1024), b""):
digest.update(chunk)
return digest.hexdigest()
with TemporaryDirectory() as directory:
path = Path(directory) / "sample.bin"
path.write_bytes(b"abc")
expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
actual = sha256_file(path)
print(f"SHA-256: {actual}")
print(f"Matches trusted value: {actual == expected}")
SHA-256: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
Matches trusted value: True
Der Code erstellt eine kleine Beispieldatei, sodass er unverändert ausgeführt werden kann. Ersetzen Sie in Ihrem eigenen Skript path durch den Pfad der heruntergeladenen Datei. Legen Sie bei einer heruntergeladenen Datei path auf ihren Speicherort fest und vergleichen Sie den berechneten Digest mit einem vertrauenswürdigen Referenzwert für diese Datei.
Eine Datei mit einer vertrauenswürdigen Prüfsumme überprüfen
Speichern Sie den erwarteten Digest oder beziehen Sie ihn unabhängig, und vergleichen Sie ihn anschließend mit dem von sha256_file zurückgegebenen Wert. Der boolesche Vergleich im Beispiel ist wahr, wenn die beiden Hexadezimalzeichenfolgen übereinstimmen. Ein falsches Ergebnis bedeutet, dass die Datei nicht zu diesem Referenzwert passt. Sie könnte beschädigt oder absichtlich verändert worden sein, oder es wurde der falsche Referenzwert verwendet. Laden Sie die Datei erneut herunter oder untersuchen Sie die Quelle, statt aus einer Abweichung auf eine bestimmte Ursache zu schließen.
Normalisieren Sie den erwarteten Textwert in sicherheitsrelevanten Abläufen nur entsprechend dem vom Herausgeber dokumentierten Format und vergleichen Sie anschließend den vollständigen Digest. Vergleichen Sie keinen kurzen Präfix, wenn der vollständige Digest verfügbar ist. Ein erfolgreicher Vergleich bestätigt, dass die Bytes dem vertrauenswürdigen Referenz-Digest entsprechen. Er authentifiziert den Herausgeber jedoch nur, wenn auch der Referenzwert selbst authentifiziert wurde.
Große Dateien und häufige Fehler
Beim blockweisen Lesen muss nicht die gesamte Datei in den Arbeitsspeicher geladen werden. Die gewählte Blockgröße beeinflusst die Effizienz der Ein- und Ausgabe, nicht aber den resultierenden Digest, sofern jedes Byte genau einmal und in der richtigen Reihenfolge gelesen wird. Der Binärmodus ist wichtig, denn im Textmodus können Daten dekodiert oder Zeilenenden umgewandelt werden. Lassen Sie die Datei nur während des Lesens geöffnet, wie es die with-Anweisung erledigt.
Vermeiden Sie es, bei sehr großen Dateien mit file.read() alle Bytes auf einmal einzulesen. Achten Sie außerdem darauf, dass der Pfad auf die zu überprüfende Datei verweist und für den Referenzwert derselbe Hash-Algorithmus verwendet wurde wie bei der lokalen Berechnung. Eine abweichende Schreibweise oder ein anderer Algorithmus führt zu unterschiedlichen Zeichenfolgen, selbst wenn sich der Dateiinhalt nicht geändert hat. Wird die Datei während der Berechnung verändert, kann der Digest verschiedene Dateistände widerspiegeln. Prüfen Sie daher eine stabile Kopie, wenn ein anderer Prozess die Datei möglicherweise gerade schreibt.
Einen Hash-Algorithmus auswählen und seine Grenzen kennen
Verwenden Sie SHA-256 als allgemeinen Datei-Digest, wenn ein vertrauenswürdiger Herausgeber einen Referenzwert für SHA-256 bereitstellt. Der Algorithmus ist über hashlib.sha256() verfügbar. MD5 kommt noch in älteren Beispielen und Kompatibilitätsabläufen vor, ist jedoch anfällig für Kollisionsangriffe und für sicherheitsrelevante Integritätsprüfungen ungeeignet. Verwenden Sie MD5 weder zum Nachweis der Authentizität noch zum Schutz vor einem gezielten Angreifer.
Prüfsummen unterscheiden sich auch vom Passwort-Hashing: Ein schneller Digest eignet sich für den Dateivergleich, während Passwörter speziell entwickelte, gesalzene Passwort-Hashing-Verfahren erfordern. In jedem Fall kann der Digest nur beantworten, ob die Bytes einem Referenzwert entsprechen. Ob dieser Wert vertrauenswürdig ist, hängt davon ab, wie er bezogen und geschützt wurde.