Artefaktmanifeste mit b2sum und GNU Parallel verifizieren
Erfassen Sie mit GNU b2sum einen vollständigen Satz fertiger Artefakte.
Prüfen Sie ihn anschließend, ohne die erwarteten Werte neu zu erzeugen. Diese Anleitung hasht ein
kleines Backup-Verzeichnis parallel, ersetzt das Manifest erst nach erfolgreichem Abschluss aller
Hash-Berechnungen und gibt Verifizierungsfehler an die Shell oder einen CI-Job weiter.
Ein Hashwert allein belegt nicht, wer eine Datei erstellt hat: Beziehen Sie die erwartete Prüfsumme über einen vertrauenswürdigen Kanal, etwa ein authentifiziertes Release oder ein signiertes Manifest, statt Datei und Prüfsumme gemeinsam aus einer nicht vertrauenswürdigen Quelle herunterzuladen.
Das passende Prüfsummenformat wählen
GNU b2sum
verwendet standardmäßig BLAKE2b-512, dargestellt als 128 hexadezimale Zeichen. Verwenden Sie denselben
Algorithmus und dieselbe Hashwertlänge wie bei den erwarteten Werten. BLAKE2s und SHA-256 sind andere
Formate. Wenn ein Herausgeber SHA-256 bereitstellt, verifizieren Sie mit
sha256sum, statt aus dem Download eine eigene BLAKE2-Referenz zu erzeugen.
Dieses Beispiel erstellt eine lokale Referenz aus bekannten Dateien. Erzeugen Sie das Manifest in einem Release-Workflow auf der vertrauenswürdigen Erzeugerseite, nachdem die Artefakte fertiggestellt sind. Schützen Sie anschließend seine Herkunft und seinen Inhalt. Wer sowohl Artefakte als auch erwartete Werte ersetzen kann, kann die Verifizierung erfolgreich durchlaufen lassen.
Die Linux-Voraussetzungen prüfen
Verwenden Sie Linux mit Bash, GNU coreutils, GNU findutils, GNU Parallel und Python 3. Unter Debian
oder Ubuntu heißen die entsprechenden Pakete bash,
coreutils, findutils, parallel
und python3.
GNU Parallel wird separat installiert; ein anderer Befehl namens parallel
ist kein Ersatz. Prüfen Sie die Verfügbarkeit, bevor Sie das Beispielverzeichnis erstellen:
bash --version && b2sum --version && find --version && parallel --version && python3 --version
Das Beispiel wurde mit Bash 5.3.15, coreutils 9.11, findutils 4.11.0, GNU Parallel 20240222 und Python 3.14.7 getestet. Python erstellt nur die Beispieldateien und benötigt keine Pakete von Drittanbietern. Dies ist ein lokaler Linux-Workflow, keine Anleitung für macOS oder Windows.
Einen kleinen Artefaktsatz erstellen
Beginnen Sie in einem Verzeichnis, das Sie kontrollieren. Dieser Befehl wechselt in ein neues Verzeichnis und verweigert die Wiederverwendung eines bereits vorhandenen:
mkdir -- integrity-demo && cd -- integrity-demo
Legen Sie die übrigen Dateien in integrity-demo ab und führen Sie dort die weiteren
Befehle aus. Speichern Sie Folgendes als make-fixture.py:
from pathlib import Path
root = Path('backups')
root.mkdir()
(root / 'archive').mkdir()
samples = {
'app.tar': b'first release\n',
'archive/app.tar': b'other release\n',
'empty.tar': b'',
'-draft.tar': bytes([0, 255, 16, 10]),
'café copy.tar': b'Unicode name\n',
'line\nbreak.tar': b'newline name\n',
}
for name, content in samples.items():
(root / name).write_bytes(content)
Führen Sie das Skript einmal aus:
python3 -I make-fixture.py
Diese sechs kleinen Dateien decken leere und binäre Inhalte, doppelte Basisnamen, Leerzeichen,
Unicode und einen Zeilenumbruch in einem Dateinamen ab. Sie enthalten Beispieldaten mit der Endung
.tar und sind keine echten tar-Archive.
Der Generator verweigert die Ausführung, wenn das Verzeichnis backups
bereits existiert. Wird die Einrichtung unterbrochen, prüfen Sie das unvollständige Verzeichnis und
beginnen Sie ein neues Beispiel in einem unbenutzten Verzeichnis. Ein erneuter Generatorlauf
repariert oder überschreibt die bisherigen Dateien nicht.
Ein vollständiges Manifest erzeugen
Speichern Sie dies als hash-backups.sh. Führen Sie es als gespeichertes Bash-Skript
aus, statt es in Ihre Shell einzufügen:
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
umask 077
if (( $# != 1 )) || [[ -z $1 ]]; then
printf 'Usage: bash hash-backups.sh BACKUP_DIR\n' >&2
exit 2
fi
backupDir=$1
if [[ $backupDir != /* ]]; then
backupDir=./$backupDir
fi
if [[ ! -d $backupDir ]]; then
printf 'Not a directory: %s\n' "$backupDir" >&2
exit 2
fi
tempDir=$(mktemp -d .checksums.XXXXXX)
trap 'rm -rf -- "$tempDir"' EXIT
find "$backupDir" -type f -name '*.tar' -print0 > "$tempDir/files.nul"
if [[ ! -s $tempDir/files.nul ]]; then
printf 'No .tar files selected in %s\n' "$backupDir" >&2
exit 1
fi
sort -z "$tempDir/files.nul" |
parallel --plain --will-cite --tmpdir "$tempDir" -0 --jobs 4 \
--keep-order --halt now,fail=1 b2sum -- {} > "$tempDir/checksums.b2"
test -s "$tempDir/checksums.b2"
mv -fT -- "$tempDir/checksums.b2" checksums.b2
Führen Sie das Erzeugerskript aus:
bash hash-backups.sh backups
Es wählt rekursiv reguläre Dateien mit der kleingeschriebenen Endung
.tar aus, ohne symbolischen Links zu folgen. GNU Parallel führt bis zu
vier Hash-Jobs aus, gruppiert deren Ausgabe und behält die sortierte Eingabereihenfolge bei. Die
Option --plain ignoriert persönliche
Profile und Einstellungen aus PARALLEL, während
--halt now,fail=1 bei einer fehlgeschlagenen Hash-Berechnung stoppt. Eine leere Auswahl,
ein fehlgeschlagener Verzeichnisdurchlauf oder eine fehlgeschlagene Hash-Berechnung führt zum
Abbruch mit einem Exit-Status ungleich null, bevor checksums.b2 ersetzt wird.
Das temporäre Verzeichnis liegt neben dem Ziel. So veröffentlicht der abschließende Aufruf von
mv das fertige Manifest durch Umbenennen im selben Dateisystem.
Ein erfolgreicher erneuter Lauf ersetzt das bisherige Manifest; bei Fehlern bleibt es erhalten und
temporäre Dateien werden entfernt. Führen Sie immer nur ein Erzeugerskript gleichzeitig aus und
lassen Sie das Artefaktverzeichnis während des Durchlaufens, Hashens oder Verifizierens unverändert.
Dies ist kein Dateisystem-Snapshot.
Die erfassten Dateien verifizieren
Führen Sie die Prüfung aus demselben Verzeichnis integrity-demo aus und lassen Sie
checksums.b2 unverändert:
b2sum --check --strict --quiet checksums.b2 && printf 'All recorded files match checksums.b2\n'
All recorded files match checksums.b2
--check
liest die Pfade im Manifest. Diese Pfade enthalten Verzeichnisse, sodass die beiden Dateien namens
app.tar unterscheidbar bleiben. Relative Pfade werden ausgehend von Ihrem
aktuellen Verzeichnis aufgelöst, nicht vom Verzeichnis des Manifests. Kopieren Sie beim Prüfen eines
übertragenen Satzes die vollständige Verzeichnisstruktur zusammen mit dem Manifest.
find -print0 und parallel -0 erhalten die Grenzen zwischen
Dateinamen. Das Manifest selbst verwendet das
zeilengetrennte GNU-Format mit Escape-Sequenzen,
das Zeilenumbrüche und Backslashes in Dateinamen darstellen kann. Teilen Sie seine Datensätze nicht
an Leerraumzeichen auf und fügen Sie nicht b2sum --zero hinzu: Eine durch
NUL-Zeichen getrennte Prüfsummenausgabe wird
von --check nicht unterstützt.
Ändern Sie nun nur das vorgesehene Artefakt und wiederholen Sie den Verifizierungsschritt:
printf 'changed release\n' >> backups/app.tar &&
b2sum --check --strict --quiet checksums.b2
Der Befehl endet mit einem Exit-Status ungleich null und meldet eine abweichende Prüfsumme für
./backups/app.tar, obwohl backups/archive/app.tar weiterhin existiert.
Auch eine fehlende oder unlesbare erfasste Datei führt zum Fehlschlag.
--strict lässt die Prüfung zusätzlich bei fehlerhaft formatierten
Prüfsummendatensätzen fehlschlagen. Korrigieren Sie das Artefakt oder stellen Sie es aus einer
vertrauenswürdigen Kopie wieder her, bevor Sie erneut prüfen. Würden Sie das Manifest neu erzeugen,
würden die geänderten Bytes akzeptiert.
Die Verifizierung prüft die erfassten Dateien. Sie erkennt keine neu hinzugefügten Dateien, prüft nicht die Archivstruktur und belegt nicht, wer die Artefakte erstellt hat. Wenn Sie die Referenz ändern möchten, führen Sie das Erzeugerskript erneut aus und überprüfen Sie diesen Lauf, statt zusätzliche Dateien als bereits verifiziert zu betrachten.
Fehler in CI weitergeben
Speichern Sie den Verifizierungsbefehl als verify-backups.sh, damit sein Status den
Aufrufer erreicht:
#!/usr/bin/env bash
set -euo pipefail
b2sum --check --strict checksums.b2
Führen Sie ihn aus dem Verzeichnis aus, das das vertrauenswürdige Manifest und die darin erfasste Verzeichnisstruktur enthält:
bash verify-backups.sh
Ein CI-Job kann denselben Aufruf verwenden, nachdem er ein geschütztes Manifest ausgecheckt und die Artefakte unter den erfassten Pfaden bereitgestellt hat. Erzeugen Sie das Manifest nicht im Verifizierungsjob. Prüfen Sie berechtigte Änderungen an der Referenz separat und schützen Sie den Schreibzugriff sowohl auf das Manifest als auch auf die Artefakte. Wenn Sie die Prüfausgabe per Pipe an einen anderen Befehl weitergeben, ohne den Exit-Status zu erhalten, kann eine Abweichung unbemerkt bleiben.
Die Leistung für Ihre Arbeitslast messen
Die Leistung hängt von Dateigröße, Speicher, Caching, CPU-Instruktionen und Implementierung ab.
Diese Befehle zeigen, wie Sie die Verarbeitungszeit der Beispieldatei messen. Ersetzen Sie
backups/app.tar für aussagekräftige Messungen durch eine fertiggestellte,
repräsentative Datei:
time b2sum -- backups/app.tar > /dev/null &&
time sha256sum -- backups/app.tar > /dev/null
Die winzigen Beispieldateien ermöglichen keinen aussagekräftigen Geschwindigkeitsvergleich.
Gehen Sie nicht davon aus, dass BLAKE2 immer schneller ist als hardwarebeschleunigtes SHA-256.
Beim parallelen Hashen können Zugriffe auf denselben Datenträger miteinander konkurrieren.
Testen Sie daher verschiedene Worker-Anzahlen mit Ihrem eigenen Datensatz, bevor Sie
--jobs erhöhen.
Um eine einzelne heruntergeladene Datei nach dem Verschieben zu verifizieren, nutzen Sie die separate Anleitung zur Verifizierung mit b2sum.
