Dies ist eine informative Übersetzung. Maßgeblich ist die englische Fassung; sie hat im Zweifel Vorrang. Zur englischen Fassung

Inhalt und Hashing

Wie Label 309 einen Datensatz an seinen Inhalt bindet: die hashes-Map, worauf der Hash sich festlegt und Merkle-Commitments, um viele Elemente unter einer einzigen Wurzel zu verankern.

Der Inhalts-Hash ist der eigentliche Anspruch. Alles, was ein Label-309-Datensatz über die Existenz aussagt, leitet sich aus einem kryptografischen Hash der Inhaltsbytes ab, der unter Metadaten-Label 309 on-chain (in der Blockchain) verankert wird. Diese Seite legt fest, wie dieser Hash transportiert wird, worauf er sich genau festlegt und wie eine einzige 32-Byte-Wurzel für einen beliebig großen Stapel von Elementen einstehen kann.

Die hashes-Map

Jedes Element eines Datensatzes trägt eine hashes-Map: eine CBOR-Map, die eine Algorithmen-Kennung auf einen rohen 32-Byte-Hash abbildet.

CBOR
hashes = {
  "sha2-256": h'…32 bytes…',      ; key = algorithm id, value = raw digest
}

Die Schlüssel sind Text-String-Kennungen aus der Hash-Registry; die Werte sind rohe Byte-Strings, niemals hex-kodiert. Die Map muss mindestens einen Eintrag enthalten, und jeder registrierte Hash-Algorithmus erzeugt genau 32 Byte:

KennungAlgorithmusReferenzHash
sha2-256SHA-256FIPS 180-432 B
blake2b-256BLAKE2b-256RFC 769332 B

Beide Kennungen müssen von Verifizierern zwingend implementiert werden, sodass ein Datensatz mit nur einem Hash unter einer der beiden überall validiert. Trifft ein Verifizierer auf eine unbekannte Kennung, weist er den Datensatz mit einem stabilen Fehlercode zurück, anstatt den Eintrag stillschweigend zu überspringen. Die vollständige Registry, einschließlich reservierter Post-Quanten-Slots, finden Sie unter Algorithmen-Registries.

Eine CBOR-Map zu verwenden, statt paralleler Arrays oder einer Liste von {alg, digest}-Unterobjekten, hat drei Konsequenzen, die Teil des Wire-Vertrags sind. Doppelte Algorithmen sind konstruktionsbedingt ausgeschlossen, weil CBOR-Map-Schlüssel eindeutig sind. Die kanonische Reihenfolge ergibt sich von selbst, denn kanonisches CBOR sortiert die Schlüssel nach ihren kodierten Bytes; so geben zwei Erzeuger, die dieselbe Hash-Menge ausdrücken, byte-identische Maps aus, und jede Signatur auf Datensatzebene über diese Maps bleibt stabil. Und die Struktur kommt ohne Validierung pro Eintrag aus: Ein struktureller Validator prüft lediglich, ob jeder Schlüssel registriert ist und jeder Wert die Hash-Länge des Algorithmus hat.

Worauf sich der Hash festlegt

Der Hash legt sich auf die Inhaltsbytes fest, also auf genau die Bytefolge, für die der Erzeuger einen Zeitstempel setzt. Jeder Eintrag einer hashes-Map muss der Hash genau dieser Bytefolge unter dem jeweils benannten Algorithmus sein; ein Datensatz, dessen Einträge unterschiedliche Klartexte beschreiben, ist nicht konform. Stehen einem Verifizierer die Inhaltsbytes zur Verfügung, muss er jeden Hash neu berechnen und den Datensatz zurückweisen, falls auch nur einer nicht übereinstimmt.

Trägt ein Datensatz einen Verschlüsselungsumschlag (enc), bindet der Hash den Klartext, niemals den Chiffretext. Das ist beabsichtigt: Ein Existenznachweis (engl. Proof of Existence, PoE) besteht, damit ein Urheber später den Klartext offenlegen und beweisen kann, dass dieser zu einem bestimmten Zeitpunkt existierte. Würde man den Chiffretext hashen, bewiese das nur, dass irgendein verschlüsselter Datenblock existierte, was über den zugrunde liegenden Inhalt nichts aussagt. Ein versiegelter Datensatz beweist daher weiterhin genau, welcher Klartext mit einem Zeitstempel versehen wurde: Der Empfänger entschlüsselt, berechnet die Klartext-Hashes neu und gleicht sie mit dem On-Chain-Commitment ab. Ein Element mit enc muss deshalb mindestens einen Inhalts-Hash-Eintrag tragen; ohne ihn gäbe es keinen Klartext-Anspruch, gegen den neu berechnet werden könnte.

Klartextbindung, auch im versiegelten Fall

Der On-Chain-Hash eines versiegelten Datensatzes ist der Hash des Klartexts. Der Chiffretext selbst liegt unter einer inhaltsadressierten ar://- oder ipfs://-URI, sodass die Bytes, die ein Speicher-Gateway zurückgibt, gegen die Adresse manipulationssichtbar sind, ohne dass man dem Gateway vertrauen muss; ein Empfänger entschlüsselt und berechnet den Klartext-Hash neu, um den Kreis zurück zum On-Chain-Anspruch zu schließen.

Ein Hash oder mehrere

Ein einziger Inhalts-Hash ist vollständig konform. Für alle 256-Bit-Hashes der Registry liegen die besten bekannten Second-Preimage-Angriffe klassisch bei oder nahe 2^256. Ein einziger solider 256-Bit-Hash deckt damit das realistische Bedrohungsmodell über die Archivlebensdauer eines Datensatzes bereits ab, und strukturelle Validatoren geben für Datensätze mit nur einem Eintrag keine Warnung aus.

Ein Erzeuger kann als optionale Verteidigung in der Tiefe einen zweiten Eintrag aus einer unabhängigen Designfamilie hinzufügen, indem er sha2-256 (SHA-2: Merkle–Damgård) mit blake2b-256 (BLAKE2: eine HAIFA-Konstruktion über einer von ChaCha abgeleiteten Permutation) kombiniert. Da die beiden Familien keine strukturelle Verwandtschaft teilen, wird ein Datensatz, der beide trägt, nur dann geschwächt, wenn beide Familien gleichzeitig der Kryptoanalyse erliegen. Die Kosten betragen einen zusätzlichen 32-Byte-Hash samt kurzer Kennung pro Element; die Wahl liegt beim Erzeuger und ist niemals verpflichtend.

Merkle-Batch-Commitments

Ein einzelner Inhalts-Hash verankert einen einzelnen Inhalt. Um eine beliebig große Sammlung zu verankern, etwa einen CI-Artefaktsatz aus 500 Dateien, einen Strom von IoT-Ereignissen oder einen Stapel aus einem Audit-Log, definiert Label 309 ein merkle[]-Array auf oberster Ebene. Jeder Eintrag legt sich auf eine geordnete Liste von 32-Byte-Blättern fest, wobei eine einzige 32-Byte-Wurzel on-chain veröffentlicht wird; die geordneten Blätter selbst liegen off-chain.

CBOR
merkle = [
  {
    "alg":        "rfc9162-sha256",
    "root":       h'…32 bytes…',   ; canonical root over the ordered leaves
    "leaf_count": 4,               ; binds the on-chain root to the leaf-list size
    "uris":       [ … ],           ; OPTIONAL — where the off-chain leaves list lives
  },
]

Der registrierte Commitment-Algorithmus ist rfc9162-sha256: der Merkle Tree Hash aus RFC 9162 §2.1.1, mit SHA-256 als zugrunde liegendem Hash. Es handelt sich um eine Listen-Commitment-Konstruktion, die von der Inhalts-Hash-Registry getrennt ist: Eine Merkle-Wurzel legt sich auf eine Blattlisten-Struktur fest, ein sha2-256-Hash auf Klartextbytes, und deshalb steht sie in einem eigenen Array statt innerhalb von hashes. Das On-Chain-leaf_count bindet die Wurzel an die Größe der Off-Chain-Liste und schließt eine Vertauschung aus, die für eine bestimmte Blattposition einen anders großen Baum mit derselben Wurzel rekonstruiert.

Baumkonstruktion

Die Konstruktion unterscheidet Blätter von inneren Knoten durch ein Domänentrennungspräfix aus einem Byte, 0x00 für Blätter und 0x01 für innere Knoten, sodass ein Angreifer keinen inneren Knoten erzeugen kann, der mit einem Blatt kollidiert. Für eine geordnete Liste L = (d_0, …, d_{n-1}) aus 32-Byte-Werten mit n ≥ 1 ist der Merkle Tree Hash rekursiv definiert:

MTH(L) = SHA-256(0x00 || d_0)                            when n == 1
MTH(L) = SHA-256(0x01 || MTH(L[0:k]) || MTH(L[k:n]))     when n > 1
         where k is the largest power of 2 strictly less than n

Eine entscheidende Folge: Ein einzelnes Blatt wird als SHA-256(0x00 || d_0) gehasht, nicht als das bloße Blatt. Die Wurzel eines Baums mit einem Blatt ist daher niemals gleich dem Blatt selbst. Erzeuger, die einen einzelnen Inhalt mit einem Zeitstempel versehen wollen, müssen direkt einen einfachen sha2-256- oder blake2b-256-Eintrag verwenden, keinen Merkle-Baum mit einem einzigen Blatt. Ein leerer Baum (n == 0) ist unzulässig.

Die Konstruktion ist reihenfolgeabhängig, denn das Umordnen der Blätter ergibt eine andere Wurzel. Erzeuger müssen die Blattliste daher als geordnete Folge behandeln und diese Reihenfolge über Veröffentlichung, Archivierung und jede spätere Beweiserzeugung hinweg erhalten.

Die Off-Chain-Blattliste

Die Wurzel ist ohne die Blattliste nutzlos, deshalb bewahren Erzeuger die geordneten Blätter off-chain auf. Das kanonische Artefakt ist ein Dokument vom Typ cardano-poe-merkle-leaves-v1, kodiert als kanonisches CBOR (RFC 8949): eine 32-Byte-Wurzel, das geordnete Array der 32-Byte-Blätter und die Blattanzahl.

CDDL
leaves-list = {
  "format":     "cardano-poe-merkle-leaves-v1",
  "tree_alg":   tstr,                   ; registered list-commitment algorithm id
  "root":       bytes .size 32,         ; raw 32 bytes, not hex
  "leaves":     [ + bytes .size 32 ],   ; ordered raw 32-byte leaves
  "leaf_count": 1..4294967295,          ; 1 .. 2^32-1; MUST equal the length of `leaves`
  ? "leaf_alg": tstr,                   ; informative; no verification semantics
}

Ein Verifizierer löst die Off-Chain-Liste auf, berechnet die Wurzel aus deren leaves mit der oben beschriebenen Konstruktion neu und gleicht sie Byte für Byte mit der On-Chain-merkle[i].root ab; das leaf_count in der Datei muss sowohl dem On-Chain-leaf_count als auch len(leaves) entsprechen. Dieser kanonische CBOR-Container ist die einzige normative Form der Blattliste – es gibt keine JSON-Projektion und keine alternative Serialisierung, sodass zwei Implementierungen, die eine Blattliste austauschen, stets byte-vergleichbare Dokumente austauschen.

Inklusionsbeweise

Der Sinn des Batchings ist die selektive Offenlegung: nachzuweisen, dass ein Element in der festgeschriebenen Liste enthalten war, ohne den Rest erneut zu veröffentlichen oder auch nur offenzulegen. Ein Inklusionsbeweis für ein Blatt ist die geordnete Liste der Hashes der Geschwisterknoten entlang des Pfades von diesem Blatt zur Wurzel: ein Geschwisterpfad der Länge O(log n). Ein Verifizierer faltet das Blatt und die Geschwister gemäß RFC 9162 wieder den Baum hinauf und akzeptiert den Beweis genau dann, wenn die rekonstruierte Wurzel Byte für Byte der veröffentlichten Wurzel entspricht.

Da RFC-9162-Bäume nicht auf eine Zweierpotenz aufgefüllt werden, kann ein Blatt am rechten Rand eines unausgeglichenen Baums einen kürzeren Pfad haben als ein Blatt auf der voll besetzten Seite. Die maßgebliche Prüfung ist daher algorithmisch, nämlich ob die Faltung die Wurzel reproduziert, und niemals ein Vergleich der Beweislänge.

Warum Batching wichtig ist

Eine einzige Transaktion und eine einzige 32-Byte-Wurzel können für Tausende oder Millionen Blätter einstehen. Wer einen O(log n)-Beweis besitzt, kann später zeigen, dass ein Element in der eigenen Liste enthalten war, während jedes nicht offengelegte Blatt privat bleibt: Die Wurzel verrät nichts über die Blätter, auf die sie sich festlegt.