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.
Ein Label-309-Datensatz ist eine einzelne CBOR-Map, die in den Metadaten einer Cardano-Transaktion unter Label 309 transportiert wird. Die Map verankert einen oder mehrere Inhalts-Hashes in der Blockchain; die Blockzeit der Transaktion ist der Zeuge dafür, dass diese Bytes spätestens zu diesem Zeitpunkt existierten. Alles Übrige, was der Datensatz tragen kann, also Speicher-URIs, ein Verschlüsselungsumschlag, Signaturen zur Urheberschaft oder ein Verweis auf einen abgelösten Datensatz, sind optionale Metadaten zu diesem Kernanspruch.
Diese Seite definiert die On-Wire-Struktur: wo der Datensatz liegt, wie er kodiert wird, wie übergroße Werte transportiert werden und gegen welches geschlossene Schema ein struktureller Validator prüft. Die hier referenzierten kryptografischen Konstruktionen (Hash-Verfahren, der versiegelte Umschlag, Signaturen) haben eigene Seiten; diese hier behandelt das Wire-Format.
Wo der Datensatz liegt
Ein PoE-Datensatz MUSS unter dem Transaktions-Metadaten-Label 309 abgelegt
werden, das in der
CIP-10 Metadaten-Label-Registry
als "Proof of Existence record" reserviert ist. Transaktionsmetadaten sind eine Map
von einem Integer-Label auf einen Wert, daher DARF eine Transaktion NICHT
mehr als einen PoE-Datensatz tragen, also genau einen Datensatz pro Transaktion.
Eine Transaktion DARF zusätzliche Metadaten unter anderen Labels tragen (zum
Beispiel eine
CIP-20-Nachricht
unter 674). Eine prüfende Stelle, die eine PoE verarbeitet, MUSS jedes Label
außer 309 ignorieren.
Im Ledger der Conway-Ära sind die Transaktionsmetadaten das Feld metadata
innerhalb der auxiliary_data der Transaktion. Die unter einem beliebigen Label
zulässigen Werte sind auf den rekursiven Typ metadatum des Ledgers beschränkt:
Integer, Byte-Strings, Text-Strings, Arrays und Maps, wobei sowohl Byte-Strings
als auch Text-Strings jeweils auf 64 Byte begrenzt sind:
metadatum =
{ * metadatum => metadatum }
/ [ * metadatum ]
/ int
/ bstr .size (0..64)
/ tstr .size (0..64)Eine Transaktion, die einen einzelnen bstr oder tstr länger als 64 Byte trägt,
wird von Cardano-Knoten bei der Einreichung abgewiesen, noch bevor irgendeine
prüfende Stelle sie zu Gesicht bekommt. Diese Begrenzung ist der Grund, warum Label
309 eine Disziplin für das Transport-Chunking definiert (siehe unten); jedes Feld,
das der Datensatz trägt, ob Basis- oder Erweiterungsfeld, muss sich auf ein
metadatum reduzieren lassen.
Transport: das Chunk-Array über den gesamten Körper
Ein serialisierter Datensatzkörper überschreitet routinemäßig 64 Byte und kann
deshalb nicht als bloßer Wert unter Label 309 gespeichert werden. Der Datensatzkörper
wird daher als undurchsichtiges Chunk-Array über den gesamten Körper transportiert:
ein einziges CBOR-Array aus Byte-Strings von höchstens 64 Byte (bstr .size (1..64)),
dessen Konkatenation in der vorgegebenen Reihenfolge der Datensatzkörper ist. Diese
Transport-Aufteilung ist die einzige Aufteilung, die Label 309 vornimmt – der eine
wirklich vom Ledger erzwungene Schritt im Format.
Da das Ledger nur dieses Transport-Array sieht und nie die Felder innerhalb des wieder
zusammengesetzten Körpers, sind diese Felder gewöhnliche CBOR-Werte ohne Chunk-Wrapper
pro Feld und ohne 64-Byte-Grenze auf Feldebene: Eine Speicher-URI ist ein einziger
Text-String, ein COSE_Sign1 ist ein einziger Byte-String, und ein X-Wing-kem_ct ist
ein einziger 1120-Byte-Byte-String. Ein Feld, das länger als 64 Byte ist, reicht einfach
über die Chunk-Grenzen des Arrays über den gesamten Körper hinweg, wie jeder andere
Abschnitt des Körpers auch.
Ein Erzeuger MUSS den Datensatzkörper einmal zu kanonischem CBOR serialisieren, diesen Byte-String in Chunks von 1 bis 64 Byte aufteilen und das resultierende Array fester Länge aus Byte-Strings fester Länge als Label-309-Wert speichern. Die Array-Form ist immer erforderlich, selbst für einen Körper von 64 Byte oder weniger: Ein solcher Körper ist ein Array der Länge 1, niemals eine bloße Map oder ein bloßer Byte-String. Erzeuger SOLLTEN die minimale Aufteilung verwenden (jeder Chunk außer dem letzten exakt 64 Byte) und SOLLTEN keine Chunks der Länge null ausgeben; eine übermäßige Aufteilung verschwendet Transaktionsbytes ohne jeden Nutzen.
Eine prüfende Stelle MUSS die Array-Elemente in der vorgegebenen Reihenfolge byteweise
verketten, um den Datensatzkörper vor der Strukturprüfung wieder zusammenzusetzen, und
MUSS jeden Label-309-Wert zurückweisen, der nicht ein solches Array ist. Die
Chunk-Grenzen tragen keine semantische Bedeutung: Zwei Transport-Arrays, deren
Konkatenationen byteidentisch sind, bezeichnen denselben Datensatz. Die Taxonomie der
Transportfehler legt die Ablehnungscodes fest – ein Chunk, der länger als 64 Byte ist, ist
CHUNK_TOO_LARGE; ein Array-Element, das kein Byte-String ist, ein Array oder Element
unbestimmter Länge oder ein Label-309-Wert, der kein Array ist (bloße Map, bloßer
Byte-String, Integer), ist MALFORMED_CBOR. Ein Chunk der Länge null steuert keine Bytes
bei und wird toleriert, nie für sich allein zurückgewiesen.
Das Schema beschreibt den wieder zusammengesetzten Körper
Alles Folgende (die Datensatz-Map, das CDDL, die Feldregeln) beschreibt den Datensatzkörper nach der Wiederzusammensetzung der Chunks. Das Chunk-Array über den gesamten Körper ist nicht Teil des Schemas; es wird zuerst rückgängig gemacht, dann wird der Körper validiert.
Die Datensatz-Map
Der wieder zusammengesetzte Datensatzkörper ist eine CBOR-Map. Integer-wertige Felder sind CBOR-Major-Type 0/1; Textfelder sind Major Type 3 und MÜSSEN gültiges UTF-8 sein; Byte-Felder sind Major Type 2; Arrays sind Major Type 4; verschachtelte Maps sind Major Type 5. Ein optionales Feld, das vorhanden ist, DARF KEINEN leeren Wert tragen.
Die Struktur der obersten Ebene ist:
| Schlüssel | Typ | Status | Bedeutung |
|---|---|---|---|
v | uint | ERFORDERLICH | Schemaversion; dieses Dokument definiert v = 1. |
items | Array von Item-Maps | OPTIONAL | Festlegungen je Inhalt (siehe Inhalt und Hashing). |
merkle | Array von Festlegungen | OPTIONAL | Listenfestlegungen, die Off-Chain-Leaf-Listen an eine Wurzel binden. |
supersedes | bytes (32) | OPTIONAL | Transaktions-Hash eines früheren Datensatzes, den dieser ablöst. |
sigs | Array von Signatur-Maps | OPTIONAL | Urheberschafts-Signaturen auf Datensatzebene (siehe Signaturen). |
crit | Array von Text-Strings | OPTIONAL | Erweiterungsschlüssel, die zwingend verstanden werden müssen. |
Ein konformer Datensatz MUSS mindestens eines von items (mit ≥ 1 Eintrag)
oder merkle (mit ≥ 1 Eintrag) festlegen. Ein Datensatz, der weder das eine noch
das andere trägt, oder eines von beiden als leeres Array, wird als leerer Datensatz
abgewiesen. Abgesehen von dieser Regel sind items und merkle orthogonal: Ein
Datensatz darf eines von beiden allein oder beide zusammen tragen.
Label 309 schreibt keine zahlenmäßige Obergrenze für die Anzahl der Einträge vor. Die einzige Schranke ist die aktuelle maximale Transaktionsgröße von Cardano, und Erzeuger zahlen byteabhängige Gebühren, die die Datensatzgröße auf natürliche Weise begrenzen. Ein Validator DARF einen Datensatz NICHT allein deshalb abweisen, weil er viele Einträge trägt, solange er innerhalb des Größenlimits des Ledgers bleibt.
Das Versionsfeld
v ist ein vorzeichenloser CBOR-Integer, kein String im Format einer semantischen
Version. Dieses Dokument definiert genau v = 1. Ein Validator MUSS einen
Datensatz, dessen v außerhalb der unterstützten Menge liegt, mit einem
typisierten Fehler abweisen; er DARF NICHT abstürzen, abbrechen oder den
Datensatz stillschweigend als ein anderes Metadaten-Schema behandeln. Der
Integer v wird nur dann erhöht, wenn eine Änderung dazu führen würde, dass ein
v1-Parser den Datensatz falsch interpretiert; additive, mit Namensraum versehene
Erweiterungen erhöhen ihn nicht.
Items
Jeder Eintrag in items ist eine CBOR-Map mit einem erforderlichen und zwei
optionalen Feldern:
hashes: ERFORDERLICH, eine nicht leere Map von einer Hash-Verfahrens-Kennung auf den rohen 32-Byte-Digest. Mindestens ein Eintrag; doppelte Verfahren sind unmöglich, da CBOR-Map-Schlüssel eindeutig sind. Siehe Inhalt und Hashing.uris: OPTIONAL, eine plurale Liste von Discovery-URIs (Regeln siehe unten).enc: OPTIONAL, der Verschlüsselungsumschlag für ein versiegeltes Item. Siehe Versiegelte PoE.
Es gibt keinen Signatur-Slot je Item. Die Urheberschaft wird ausschließlich auf
Datensatzebene ausgedrückt, durch einen Eintrag in sigs[], der jedes Item
einheitlich abdeckt.
Merkle-Festlegungen
Jeder Eintrag in merkle bindet den Datensatz über eine kanonische
Hash-Baum-Konstruktion an eine geordnete Liste von 32-Byte-Leaves, sodass eine
einzige 32-Byte-Wurzel in der Blockchain für eine beliebig große Off-Chain-Liste
von Leaves stehen kann. Eine Festlegung ist eine geschlossene Map:
| Feld | Typ | Status | Bedeutung |
|---|---|---|---|
alg | tstr | ERFORDERLICH | Registrierte Kennung des Listenfestlegungs-Verfahrens. |
root | bytes (32) | ERFORDERLICH | Kanonische Wurzel über die geordnete Leaf-Liste des Erzeugers. |
leaf_count | uint | ERFORDERLICH | Anzahl der festgelegten Leaves; bindet die Wurzel an die Listengröße. |
uris | URI-Liste | OPTIONAL | Inhaltsadressierte URI(s) für die Off-Chain-Datei der Leaf-Liste. |
Eine Merkle-Wurzel legt eine Leaf-Listen-Struktur fest, während ein Eintrag in
hashes Klartext-Bytes festlegt; beide werden unterschiedlich verifiziert
(Inklusionsbeweis gegenüber Klartext-Neuberechnung), weshalb Listenfestlegungen auf
der obersten Ebene liegen und nicht innerhalb eines Items. Die Registry der
Listenfestlegungen ist von der Registry der Inhalts-Hashes getrennt, siehe
Algorithmen-Registries.
Supersedes
supersedes ist ein optionaler 32-Byte-Cardano-Transaktions-Hash, der auf einen
früheren Label-309-Datensatz verweist. Es handelt sich um eine
dienstunabhängige, ausschließlich anhängende Verknüpfung: Ein späterer Datensatz
kann auf einen früheren verweisen, ohne Off-Chain-Datenbank und ohne herstellereigene
Datensatz-ID.
Eine Ablösung entfernt, widerruft oder entwertet den früheren Datensatz NICHT, denn die Blockchain ist ausschließlich anhängend, und prüfende Stellen MÜSSEN den früheren Datensatz weiterhin als existent und eigenständig überprüfbar behandeln. Der Verweis trägt kein Begründungs- oder Freitextfeld; jede menschliche Bedeutung (Korrektur, Ersetzung, Rückzug) gehört in den neuen Inhalt, nicht in Label 309. Eine prüfende Stelle, die den Verweis auflöst, MUSS ihn im selben Cardano-Netzwerk nachschlagen wie die enthaltende Transaktion; das Feld trägt keinen Netzwerk-Diskriminator, da ein Transaktions-Hash nur innerhalb seines eigenen Netzwerks eindeutig ist.
Signaturen
sigs ist ein optionales Array von Signatur-Einträgen auf Datensatzebene. Jeder
Eintrag trägt eine abgetrennte
COSE_Sign1-Struktur über den
Datensatzkörper, also über die vollständige Datensatz-Map mit entferntem sigs,
und optional den öffentlichen Schlüssel (Public Key) des Signierenden für den Pfad
der Wallet-Signatur. Eine einzelne Signatur bezeugt den gesamten Körper: jedes
Item, jede URI, jeden Umschlag, den Ablösungsverweis, falls vorhanden, und alle
Erweiterungsschlüssel. Signaturen sind stets optional, und ein nicht erkanntes
Signatur-Verfahren entwertet den Inhaltsanspruch niemals. Die signierten Nutzdaten,
das Präfix zur Domänentrennung, die Auflösung des Signierschlüssels und die strengen
Verifikationsregeln sind unter Signaturen festgelegt.
URI-Regeln
Wenn vorhanden, ist uris eine nicht leere Liste; jeder Eintrag ist ein einziger
CBOR-Text-String, der genau eine URI trägt. Es gibt keine Längengrenze pro URI und
keine umhüllende Form: Der Transport über den gesamten Körper erfüllt bereits die
64-Byte-String-Grenze des Ledgers, sodass eine lange ipfs://<CIDv1>/<path>-URI ein
Text-String wie jeder andere ist. Jede URI MUSS absolut sein, MUSS ein Schema
und einen hierarchischen Teil enthalten und DARF KEINEN Fragment-Bezeichner
enthalten, denn eine PoE ist ein Anspruch über Inhalts-Bytes, nicht über eine
Teilkomponente eines Dokuments.
Die Menge der Schemata in v1 ist geschlossen und inhaltsadressiert:
| Schema | Hinweise |
|---|---|
ar:// | Arweave-Transaktions-ID (43 Zeichen base64url). Form ar://<txid>. |
ipfs:// | IPFS-CID, CIDv1 bevorzugt. Form ipfs://<cid> oder ipfs://<cid>/<path>. |
Erzeuger DÜRFEN KEIN anderes Schema ausgeben; https://, http://, file://,
data: und alle weiteren werden abgewiesen. Die Beschränkung ist gewollt und nicht
vorläufig: Eine inhaltsadressierte URI bindet die abgerufenen Bytes über das
Integritätsmodell der Speicherschicht an die URI selbst (eine IPFS-CID ist ein
Multihash des Inhalts; eine Arweave-Transaktions-ID legt die Daten unter dem
Arweave-Konsens fest), sodass eine prüfende Stelle bestätigen kann: "Die Bytes, die
ich abgerufen habe, sind die Bytes, die der Erzeuger festgelegt hat", ohne DNS, TLS,
Gateways oder Zertifizierungsstellen vertrauen zu müssen. Ein Schema außerhalb
dieser Menge macht einen Datensatz strukturell ungültig; er validiert niemals als
valid.
uris ist durchweg optional. Ein reiner Hash-Datensatz mit weggelassenem uris
ist ein vollständiger Anspruch, die Existenz des Inhalts wird behauptet, ohne sich
auf einen Abrufkanal festzulegen. Das genaue CID-Profil (akzeptierte
Multibase-Präfixe, Codecs und Multihashes) ist Teil der Verifikationsregeln; siehe
Verifikation.
Kanonisches CBOR
Jeder Label-309-Datensatz MUSS als kanonisches CBOR gemäß RFC 8949 §4.2.1 (Core Deterministic Encoding) kodiert werden. Konkret:
- Bevorzugte (kürzeste) Serialisierung für jeden Integer.
- Kodierung mit definitiver Länge für alle Byte-Strings, Text-Strings, Arrays und Maps.
- Keine semantischen Tags (dieses Dokument verlangt keine; ein Bignum-Tag 2/3 DARF NICHT auftreten).
- Map-Schlüssel sortiert in bytweise lexikografischer Reihenfolge ihrer CBOR-Kodierung.
- UTF-8-Text-Strings ohne Byte-Order-Mark.
- Keine doppelten Schlüssel in irgendeiner Map.
- Keine Gleitkommazahlen oder nicht trivialen einfachen Werte; ein Datensatz trägt
ausschließlich Integer, Byte-Strings, Text-Strings, Arrays, Maps und (wo ein
Schema dies zulässt)
true/false/null. Gleitkommazahlen vom Major Type 7 (einschließlich eines ganzzahligen1.0), negative null undundefinedMÜSSEN abgewiesen, nicht umgewandelt werden.
Determinismus ist es, was das Format interoperabel macht: Zwei Erzeuger, die denselben logischen Datensatz ausdrücken, geben byteidentische Bytes aus, sodass eine über den Körper berechnete Signatur der einen Implementierung unter einer anderen verifiziert. Ein Validator MUSS eine nicht kanonische Kodierung abweisen. Explorer und Wallets dürfen Metadaten über eine JSON-Projektion darstellen, doch eine konforme prüfende Stelle MUSS das ursprüngliche Transaktions-CBOR validieren, niemals eine verlustbehaftete JSON-Neukodierung davon.
Vorwärtskompatibilität
Label 309 v1 reserviert eine geschlossene Menge von Basisschlüsseln: v, items,
merkle, supersedes, sigs, crit. Ein Datensatz DARF zusätzlich
Erweiterungsschlüssel tragen, deren Namen einem von zwei reservierten
Namensräumen entsprechen:
^x-.+: der Hersteller- bzw. experimentelle Namensraum.^[a-z]+-.+: der Namensraum für Begleitspezifikationen, in dem das Präfix die registrierende Spezifikation benennt.
Ein Validator MUSS Erweiterungsschlüssel dekodieren und bewahren, DARF
einen Datensatz NICHT allein deshalb abweisen, weil sie vorhanden sind, und
MUSS sie informativ darstellen, ohne zu behaupten, ihren Inhalt verifiziert zu
haben. Erweiterungsschlüssel sind Teil des signierten Körpers, sodass eine Signatur
auf Datensatzebene sie abdeckt; ein Relay kann keinen Erweiterungsschlüssel
einschleusen, nachdem die Signatur erzeugt wurde. Jeder unbekannte Schlüssel der
obersten Ebene, der auf keines der beiden Muster passt (ein Tippfehler wie
supersedess oder eine Schreibvariante wie Sigs), wird als unbekanntes Feld
abgewiesen. Die musterbasierte Toleranz bewahrt die Tippfehlererkennung auf der
Basismenge und hält zugleich einen stabilen Vorrat für künftige Ergänzungen offen.
Ein Erzeuger, der von einer prüfenden Stelle verlangt, ein Nicht-Basisfeld zu
verstehen, MUSS den Namen dieses Feldes im crit-Array der obersten Ebene
auflisten. Eine v1-prüfende-Stelle, die auf einen crit-Eintrag stößt, den sie
nicht implementiert, DARF den Datensatz NICHT als gültig melden. Jeder
crit-Eintrag MUSS auf das Muster der Erweiterungsschlüssel passen
(Basisschlüssel sind in crit verboten), MUSS ein Feld benennen, das im
Datensatz tatsächlich vorhanden ist, und MUSS eindeutig sein, sodass eine
Kritikalitätsmarkierung stets auf ein konkretes Feld zurückführbar ist, dessen
Semantik die prüfende Stelle verstehen muss. Diese Regeln folgen den
Must-understand-/Must-ignore-Präzedenzfällen in
RFC 9052 §3.1 (COSE crit)
und RFC 7515 §4.1.11
(JWS crit).
Byte-Budget
Die einzige feste Obergrenze für die Datensatzgröße ist der aktuelle
Cardano-Protokollparameter maxTxSize, also 16 384 Byte bei Protokoll-Hauptversion 10
im Mainnet, vorbehaltlich von Ledger-Parameteraktualisierungen. Label 309 schreibt
darunter keine schemaseitige Grenze vor. Datensätze, die das Limit
überschreiten, werden von Cardano-Knoten bei der Einreichung abgewiesen, sodass
keine prüfende Stelle sie je zu Gesicht bekommt; ein Validator DARF KEINE
Label-309-spezifische Obergrenze unterhalb von maxTxSize erfinden.
In der Praxis beansprucht die Nicht-Metadaten-Struktur einer Transaktion (Inputs, Outputs, Witnesses, Gebühren- und Gültigkeitsfelder) rund 245 Byte und lässt damit in der Größenordnung von 16 KB für den Label-309-Datensatz. Erzeuger SOLLTEN einige hundert Byte unterhalb des Limits anvisieren, um Gebührenschwankungen aufzufangen, und SOLLTEN die Größe des Datensatz-Kandidaten vor der Einreichung berechnen und frühzeitig abbrechen, falls er nicht passen würde. Die realistischen Formen, die passen, sind großzügig bemessen: weit über hundert Items mit einem einzelnen Hash, Dutzende von Signaturen auf Datensatzebene oder viele klassische Empfänger-Slots haben allesamt bequem in einer Transaktion Platz, und eine einzige Merkle-Wurzel legt eine unbegrenzte Off-Chain-Liste von Leaves zu festen On-Chain-Kosten von 32 Byte fest.
CDDL-Schema
Das folgende CDDL ist das strukturelle Schema für den wieder zusammengesetzten
Datensatzkörper, also die kanonischen CBOR-Bytes, die man nach dem Verketten des
unter Label 309 gespeicherten Chunk-Arrays aus ≤ 64-Byte-Stücken erhält. Der wieder
zusammengesetzte Körper ist schlichtes deterministisches CBOR: Er ist selbst kein
Ledger-metadatum, und seine Felder unterliegen nicht der 64-Byte-String-Grenze,
die allein der Transport-Wrapper über den gesamten Körper erfüllt. Der Wrapper wird
hier nicht modelliert.
Der Block beschreibt die permissive Obermenge wohlgeformter Formen;
feldübergreifende Invarianten (die items-oder-merkle-Regel, die Exklusivität
von slots ⊕ passphrase im Verschlüsselungsumschlag, die Registry-Zugehörigkeit
von Algorithmen-Kennungen, die Slot-Formregeln pro KEM) werden durch einen
typisierten Validierungsdurchlauf über die dekodierte Struktur durchgesetzt, nicht
durch das CDDL selbst.
; An extension value is any CBOR value the canonical (deterministic) encoding
; profile admits. Floats and semantic tags are excluded by that profile (they
; are rejected as MALFORMED_CBOR on decode), so the exclusion is not repeated
; here; the reassembled body carries no field-level 64-byte cap.
extension-value =
{ * extension-value => extension-value }
/ [ * extension-value ]
/ int
/ bstr
/ tstr
/ bool
/ null
; A conformant record MUST carry at least one of `items` (>= 1 entry) or
; `merkle` (>= 1 entry); a record with both absent (or both empty) is rejected
; as SCHEMA_EMPTY_RECORD by the typed pass, not at the CDDL layer.
poe-record = {
poe-common,
? "items": [ 1* item-entry ],
? "crit": [ 1* tstr ],
* extension-key => extension-value
}
poe-common = (
"v": 1,
? "merkle": [ 1* merkle-commit ],
? "supersedes": bytes32,
? "sigs": [ 1* sig-entry ],
)
extension-key = tstr .regexp "^x-.+"
/ tstr .regexp "^[a-z]+-.+"
item-entry = {
"hashes": hash-map,
? "uris": [ 1* uri ],
? "enc": enc,
}
; A non-empty CBOR map keyed by a content-hash algorithm identifier with the
; 32-byte digest as value. Map-key uniqueness makes duplicate algorithms
; structurally impossible.
hash-map = { + content-hash-alg => bytes32 }
; A list commitment binds the record to an ordered leaf list. `leaf_count`
; binds the on-chain commitment to the off-chain list size.
merkle-commit = {
"alg": merkle-commit-alg,
"root": bytes32,
"leaf_count": uint32,
? "uris": [ 1* uri ],
}
; `enc` is a choice between the scheme-1 envelope shape and a bounded opaque
; envelope (the degrade-to-opaque rule for an unsupported scheme/kem/aead). The
; typed pass enforces the slots/passphrase exclusivity and the per-KEM
; slot-shape rules over a supported envelope.
enc = enc-scheme-1 / enc-opaque
; `scheme: 1` is not a version counter for the `enc` map alone: it names the
; ENTIRE sealed cryptographic suite — the canonicalEncode rules, the slot
; schema, the HKDF and HMAC hashes, the wrap AEAD, the segmented-STREAM content
; format, the transcript schemas, the in-ciphertext passphrase commitment, the
; pinned X-Wing revision, every domain-separation label, and the Argon2id and
; passphrase-normalization profiles. Changing any one of them requires a new
; `scheme` value; see Sealed PoE for the construction it pins.
enc-scheme-1 = {
"scheme": 1,
"aead": aead-alg,
"nonce": bstr,
? "kem": kem-alg,
? "slots": [ 1* slot ],
? "slots_mac": bytes32,
? "passphrase": passphrase-block,
}
; The opaque reading of an envelope under an unsupported identifier: `scheme`
; is the only structurally required key, and every other entry is any key/value
; pair the canonical profile admits, subject to the generic decode bounds.
enc-opaque = {
"scheme": uint,
* tstr => extension-value
}
slot = classical-slot / hybrid-slot
; enc.kem = "x25519": the per-slot X25519 ephemeral public key + wrapped CEK.
classical-slot = {
"epk": bytes32,
"wrap": bytes48,
}
; enc.kem = "mlkem768x25519": the 1120-byte X-Wing ciphertext plus the wrapped
; CEK. There is NO `epk` — the X25519 ephemeral is the trailing 32 bytes of the
; X-Wing ciphertext inside `kem_ct`.
hybrid-slot = {
"kem_ct": bstr .size 1120,
"wrap": bytes48,
}
passphrase-block = {
"alg": kdf-alg,
"salt": bstr .size (16..64),
"params": { "m": uint32, "t": uint32, "p": uint32 },
}
; A signature entry is a closed map. `cose_sign1` is REQUIRED and carries the
; CBOR-encoded COSE_Sign1 as a single byte string; `cose_key` is OPTIONAL and
; carries the CBOR-encoded COSE_Key for the wallet-signing path as a single
; byte string.
sig-entry = {
"cose_sign1": bstr,
? "cose_key": bstr,
}
; A uri is one absolute URI in a single text string. The URI shape rules
; (absolute, no fragment, closed scheme set {ar://, ipfs://}) are enforced in
; the typed pass; the rule carries no length cap.
uri = tstr
bytes32 = bstr .size 32
bytes48 = bstr .size 48
; uint32 is the pinned range of every numeric field: an unsigned integer
; representable in 4 bytes (0 .. 2^32-1), handled as an exact integer.
uint32 = uint .size 4
; Algorithm-identifier strings are open `tstr`: the registries are
; authoritative for accepted values, and the typed pass emits the precise
; unsupported-algorithm code for any unrecognised identifier.
content-hash-alg = tstr ; e.g. "sha2-256", "blake2b-256"
merkle-commit-alg = tstr ; e.g. "rfc9162-sha256"
aead-alg = tstr
kem-alg = tstr
kdf-alg = tstrVerwandte Seiten
- Inhalt und Hashing: die
hashes-Map, was ein Digest festlegt und die Semantik der exakten Bytes. - Algorithmen-Registries: die benannten Kennungen für Hashes, Listenfestlegungen, AEADs, KEMs und KDFs.
- Signaturen: die Konstruktion und Verifikation von
sigsauf Datensatzebene. - Versiegelte PoE: der
enc-Umschlag und die Empfänger-Schlüssel-Slots. - Verifikation: die Validierungspipeline, das CID-Profil und der Fehlerkatalog.
Einführung
Was Label 309 ist, welche Prinzipien es garantiert und wie sich ein Datensatz überprüfen lässt, ohne einem Server vertrauen zu müssen.
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.