Zum Inhalt springen

Nachweise offline prüfen

Ein Nachweispaket ist eine ZIP-Datei, die aus dem Dashboard exportiert wird. Es enthält die Einwilligungsdatensätze, die zu ihrer Prüfung benötigten Dateien und Skripte, die die Prüfungen ausführen. Nichts auf dieser Seite erfordert eine Netzwerkverbindung oder einen HashEntry-Server.

Diese Seite gibt an, was jede Prüfung belegt. Keine einzelne Prüfung macht einen Datensatz „manipulationssicher“; zusammen ermöglichen sie es einem Dritten, Änderungen zu erkennen und einen Datensatz an einen Zeitpunkt zu binden.


DateiInhalt
consent_data.jsonDie exportierten Datensätze. Jeder Datensatz hat einen Block proof mit dem gehashten Payload.
manifest.json, metadata.jsonPaket-ID, Spezifikationsversion, Anzahl der Datensätze, package_hash.
checksums.sha256SHA-256 jeder Datei im Paket.
timestamps.tsv + *.tsrRFC-3161-Zeitstempel-Token (tsa_consent_<id>.tsr, tsa_epoch_<id>.tsr, package.tsr) und was jedes davon abdeckt.
merkle_proofs.tsvMerkle-Inklusionsbeweise (für Datensätze, die in Batches mit einem Zeitstempel versehen wurden).
verify.sh, verify.ps1, README_*.txt, proof_verification.txtPrüfskripte und Anleitungen.

Pakete gibt es in zwei Arten: unsigniert (nur Prüfsummen) und signiert (der Paket-Hash trägt zusätzlich einen RFC-3161-Zeitstempel, package.tsr).

Terminal-Fenster
# Linux / macOS
chmod +x verify.sh && ./verify.sh
Terminal-Fenster
# Windows
powershell -ExecutionPolicy Bypass -File .\verify.ps1

Die Skripte prüfen Datei-Prüfsummen, das Manifest, Zeitstempel und Merkle-Beweise. Sie berechnen den Proof-Hash nicht neu, weil dafür der geheime Schlüssel des Verantwortlichen benötigt wird (siehe unten).


Terminal-Fenster
sha256sum -c checksums.sha256 # macOS: shasum -a 256 -c checksums.sha256
sha256sum consent_data.json # muss "package_hash" in manifest.json entsprechen

Dies zeigt, dass die Dateien diejenigen sind, die im Paket aufgeführt sind. Für sich allein zeigt es nicht, wer das Paket erstellt hat oder wann — jeder kann Prüfsummen neu berechnen, nachdem er eine Datei geändert hat. Dafür ist der Zeitstempel eines signierten Pakets da.

Jeder Datensatz hat einen proof_hash. Für aktuelle Datensätze (hash_version: 2):

proof_hash = HMAC-SHA256( key = tenant secret key, message = canonical_json(payload) ) → lowercase hex

Der Payload hat immer diese elf Schlüssel (ein fehlender Wert ist null):

v (= 2), site_id, document_hash, consent_type, decision, categories, timestamp,
pii_digest, signer_digest, custom_document_hash, signature_hash
  • timestamp ist UTC mit Sekundengenauigkeit, YYYY-MM-DDTHH:MM:SS+00:00, und entspricht dem Erstellungszeitpunkt des Datensatzes.
  • Personenbezogene Daten gehen nicht direkt in den Hash ein. Sie gehen über gesalzene Digests ein: pii_digest = SHA-256( pii_salt || canonical_json({ip_address, user_agent, visitor_id}) ) und signer_digest = SHA-256( pii_salt || canonical_json(signer evidence fields) ) (oder null, wenn es keine Signatur oder Identitätsangabe gibt). Wenn ein Datensatz anonymisiert wird, werden die personenbezogenen Felder und das Salt gelöscht, die Digests bleiben jedoch erhalten, sodass der Proof-Hash weiterhin neu berechnet werden kann, während die Digests nicht mehr auf eine IP- oder E-Mail-Adresse zurückgeführt werden können.

Kanonisches JSON (HashEntry Canonical JSON v2 — dies ist nicht RFC 8785):

  1. UTF-8, kein Leerraum zwischen Tokens.
  2. Objektschlüssel sind nach UTF-8-Byte-Reihenfolge sortiert, auf jeder Ebene.
  3. Die Reihenfolge von Arrays bleibt erhalten.
  4. Ein leeres Objekt und ein leeres Array werden beide als [] geschrieben.
  5. In Zeichenketten werden nur ", \ und die Steuerzeichen U+0000–U+001F maskiert; / und Nicht-ASCII-Zeichen werden nicht maskiert.
  6. Zahlen sind ausschließlich Ganzzahlen.
  7. true, false, null in Kleinbuchstaben.

Wer ihn prüfen kann. Der Proof-Hash ist ein schlüsselbasierter Hash. Seine Neuberechnung erfordert den geheimen Schlüssel des Mandanten, daher kann er vom Verantwortlichen (der den Schlüssel besitzt) oder von einem Sachverständigen geprüft werden, dem der Verantwortliche den Schlüssel gibt. Ohne den Schlüssel kann ein Dritter ihn nicht neu berechnen — und muss es auch nicht: Die unten beschriebenen Zeitstempel- und Merkle-Prüfungen arbeiten mit dem Wert proof_hash selbst und zeigen, dass dieser Wert zum angegebenen Zeitpunkt existierte.

Terminal-Fenster
# Mit dem Schlüssel: den Proof-Hash eines Datensatzes neu berechnen (kanonischer Payload in payload.json, ohne abschließenden Zeilenumbruch)
openssl dgst -sha256 -hmac "$TENANT_SECRET_KEY" payload.json

Ältere Datensätze (hash_version: 1) verwenden SHA-256( json(payload with sorted top-level keys) || key ) und enthalten personenbezogene Daten direkt im Payload.

timestamps.tsv hat eine Zeile pro Token:

<file.tsr> <kind> <stamped data> <provider> <level at issuance>

Die gestempelten Daten sind eine Hex-Zeichenkette in Kleinbuchstaben: der proof_hash eines Datensatzes, eine Merkle-Wurzel oder der package_hash. Der Zeitstempeldienst (TSA) hat den SHA-256 der ASCII-Zeichen dieser Zeichenkette signiert, ohne abschließenden Zeilenumbruch:

Terminal-Fenster
printf '%s' "<stamped data>" > data.txt
openssl ts -verify -data data.txt -in <file.tsr> -CAfile <tsa_root.pem>
  • Das Wurzelzertifikat der TSA ist nicht im Paket enthalten. Beziehen Sie es vom Zeitstempeldienst selbst; ein Wurzelzertifikat, das von der Partei mitgeliefert wird, deren Daten Sie prüfen, würde nichts belegen.
  • Token mancher Zeitstempeldienste bestehen die ESSCertID-Prüfung von openssl ts -verify nicht. Prüfen Sie Signatur und Kette stattdessen in zwei Schritten:
Terminal-Fenster
openssl ts -reply -in <file.tsr> -token_out -out token.der
openssl cms -verify -inform DER -in token.der -CAfile <tsa_root.pem> \
-purpose timestampsign -binary -out tstinfo.der
openssl ts -reply -in <file.tsr> -text # "Message data" mit dem SHA-256 der gestempelten Daten vergleichen

Eine Zeile, deren Stufe simulated ist, ist ein Test-Zeitstempel: Sie hat keine .tsr-Datei und keinen Beweiswert.

Ein gültiges Token zeigt, dass der gestempelte Wert laut diesem Zeitstempeldienst nicht später als zu dem im Token angegebenen Zeitpunkt existierte. Ob die Zeitstempel eines bestimmten Dienstes eine gesetzliche Vermutung begründen (zum Beispiel qualifizierte Zeitstempel nach eIDAS oder Zeitstempel eines autorisierten Anbieters nach türkischem Recht), hängt vom Dienst und von der Rechtsordnung ab.

Wenn Datensätze in Batches mit einem Zeitstempel versehen werden, deckt ein Token die Merkle-Wurzel eines Batches ab, und jeder Datensatz erhält einen Inklusionsbeweis. merkle_proofs.tsv:

<consent_id> <leaf> <index> <leaf_count> <root> <epoch.tsr> <path>

Der Baum ist HashEntrys eigenes binäres SHA-256-Merkle-Schema. Er ist nicht der Baum nach RFC 6962 (Certificate Transparency), und RFC-6962-Werkzeuge können ihn nicht prüfen:

  • Blatt = der proof_hash des Datensatzes (64 Hex-Zeichen in Kleinbuchstaben), ohne zusätzliches Hashing;
  • Knoten = SHA-256 über die 128 ASCII-Zeichen hex(left) || hex(right) — die Hex-Zeichenketten, nicht die rohen Bytes;
  • eine Ebene mit einer ungeraden Anzahl von Knoten dupliziert ihren letzten Knoten;
  • es gibt kein Präfix zur Domänentrennung zwischen Blättern und Knoten.

Um einen Pfad zu prüfen, beginnen Sie mit cur = leaf und wenden Sie jeden Schritt an:

L:<h> → cur = sha256(<h> || cur)
R:<h> → cur = sha256(cur || <h>)
Terminal-Fenster
# ein Schritt, z. B. "R:<h>"
cur=$(printf '%s%s' "$cur" "$h" | sha256sum | cut -d' ' -f1)

Das Ergebnis muss <root> entsprechen. Prüfen Sie außerdem, dass 0 <= index < leaf_count gilt und dass die Anzahl der Schritte der Baumtiefe für leaf_count entspricht — die Duplizierungsregel bindet die Baumgröße nicht in die Wurzel ein, daher sind diese Werte Teil des Beweises. Prüfen Sie abschließend <epoch.tsr> gegen <root> wie in Abschnitt 3: Das belegt, wann die Wurzel und damit der Proof-Hash des Datensatzes existierte.


PrüfungBelegt
PrüfsummenDie Dateien des Pakets sind in sich konsistent.
Proof-Hash (mit dem Schlüssel)Der Inhalt des Datensatzes stimmt mit dem Hash überein, der bei seiner Erstellung berechnet wurde.
RFC-3161-TokenDer gestempelte Wert existierte laut diesem Zeitstempeldienst nicht später als zum Zeitpunkt des Tokens.
Merkle-Beweis + Epochen-TokenDer Proof-Hash des Datensatzes war Teil eines Batches, dessen Wurzel zu diesem Zeitpunkt existierte.

Was sie nicht belegen: wer die Person war (siehe identity_assurance in Dokumentzustimmung & Signatur) oder dass der Datensatz überhaupt korrekt erstellt wurde. Datensätze ohne Zeitstempel-Token stützen sich allein auf den Proof-Hash und damit auf die Geheimhaltung des Schlüssels.