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

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:

CDDL
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üsselTypStatusBedeutung
vuintERFORDERLICHSchemaversion; dieses Dokument definiert v = 1.
itemsArray von Item-MapsOPTIONALFestlegungen je Inhalt (siehe Inhalt und Hashing).
merkleArray von FestlegungenOPTIONALListenfestlegungen, die Off-Chain-Leaf-Listen an eine Wurzel binden.
supersedesbytes (32)OPTIONALTransaktions-Hash eines früheren Datensatzes, den dieser ablöst.
sigsArray von Signatur-MapsOPTIONALUrheberschafts-Signaturen auf Datensatzebene (siehe Signaturen).
critArray von Text-StringsOPTIONALErweiterungsschlü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:

FeldTypStatusBedeutung
algtstrERFORDERLICHRegistrierte Kennung des Listenfestlegungs-Verfahrens.
rootbytes (32)ERFORDERLICHKanonische Wurzel über die geordnete Leaf-Liste des Erzeugers.
leaf_countuintERFORDERLICHAnzahl der festgelegten Leaves; bindet die Wurzel an die Listengröße.
urisURI-ListeOPTIONALInhaltsadressierte 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:

SchemaHinweise
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:

  1. Bevorzugte (kürzeste) Serialisierung für jeden Integer.
  2. Kodierung mit definitiver Länge für alle Byte-Strings, Text-Strings, Arrays und Maps.
  3. Keine semantischen Tags (dieses Dokument verlangt keine; ein Bignum-Tag 2/3 DARF NICHT auftreten).
  4. Map-Schlüssel sortiert in bytweise lexikografischer Reihenfolge ihrer CBOR-Kodierung.
  5. UTF-8-Text-Strings ohne Byte-Order-Mark.
  6. Keine doppelten Schlüssel in irgendeiner Map.
  7. 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 ganzzahligen 1.0), negative null und undefined MÜ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 slotspassphrase 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.

CDDL
; 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            = tstr

Verwandte 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 sigs auf Datensatzebene.
  • Versiegelte PoE: der enc-Umschlag und die Empfänger-Schlüssel-Slots.
  • Verifikation: die Validierungspipeline, das CID-Profil und der Fehlerkatalog.