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.
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:
| Kennung | Algorithmus | Referenz | Hash |
|---|---|---|---|
sha2-256 | SHA-256 | FIPS 180-4 | 32 B |
blake2b-256 | BLAKE2b-256 | RFC 7693 | 32 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.
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 nEine 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.
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.
Der Datensatz
Das Wire-Format von Label 309. Wo der Datensatz unter Metadaten-Label 309 liegt, seine Map-Struktur, die Regeln für kanonisches CBOR, das Transport-Chunking und das CDDL-Schema.
Algorithmus-Register
Die benannten Bezeichner-Register für Hashes, AEADs, KEMs, KDFs und Signaturen sowie die Agilitätsregel, durch die der Umstieg auf Post-Quanten-Verfahren additiv erfolgt und nichts Bestehendes bricht.