Algorithm registries

The named-identifier registries for hashes, AEADs, KEMs, KDFs, and signatures — and the agility rule that makes post-quantum migration additive rather than breaking.

Every cryptographic choice in Label 309 is named by a string identifier drawn from an extensible registry — sha2-256, xchacha20-poly1305, EdDSA, and so on. A record never carries a raw algorithm number or an implicit assumption; it states which primitive it used, and a verifier looks that identifier up. This is the mechanism behind the algorithm-agile invariant: the registries can grow over time, and a verifier that meets an identifier it does not implement rejects the record with a stable, typed error — it never crashes, and it never silently accepts something it cannot check.

That single rule is what makes the migration to post-quantum algorithms additive. A new identifier is a new row in a table, not a new version of the wire format. Older records keep verifying exactly as before, and older verifiers fail closed against records they were never built to understand.

Two standing rules

Across every registry, two constraints are absolute. Implementations MUST NOT invent novel cryptography — every primitive traces to a named public standard. And all encryption MUST be authenticated: only AEAD constructions are permitted, never an unauthenticated cipher with a bolt-on (or absent) integrity check.

Hash

The content hash is the primary claim of every record, so the hash registry is the most load-bearing. Both registered functions produce a 32-byte digest, and both are mandatory for a conformant implementation to support.

IdentifierAlgorithmDigest
sha2-256SHA-256 (FIPS 180-4)32 B
blake2b-256BLAKE2b-256 (RFC 7693)32 B

A producer MAY hash the same content under both functions for defense in depth; a single hash is sufficient for a valid record.

Merkle commitment

For committing to an ordered list of leaves under a single on-chain root, Label 309 registers one Merkle-commitment identifier. It is the IANA-registered string for the SHA-256 binary Merkle tree, sharing the leaf-prefix (0x00) and internal-node-prefix (0x01) domain separation that prevents leaf/node collisions.

IdentifierAlgorithmRoot
rfc9162-sha256RFC 9162 binary Merkle tree, SHA-25632 B

A single-leaf tree commits to SHA-256(0x00 ‖ leaf), not to the bare leaf — so a one-file proof MUST use a plain hash identifier, never a 1-leaf tree.

AEAD

The AEAD registry governs which authenticated cipher protects a sealed payload on the wire. The on-wire content cipher is xchacha20-poly1305: its 24-byte nonce makes random nonces safe even across high-volume key streams, which is why it is the v1 default.

IdentifierAlgorithmKey / Nonce / TagStatus
xchacha20-poly1305XChaCha20-Poly130532 B / 24 B / 16 BMandatory — the wire AEAD
aes-256-gcmAES-256-GCMReserved (future profile)

xchacha20-poly1305 is the only identifier that may appear as the on-wire content AEAD. A separate cipher, chacha20-poly1305 (RFC 8439, 32-byte key / 12-byte nonce / 16-byte tag), is used internally to wrap a per-recipient key inside the sealed construction — it is a building block, not a wire identifier, and a record that names it in its content-AEAD slot MUST be rejected. aes-256-gcm is named but inactive; it is reserved for a future encryption profile and a v1 verifier rejects any record that selects it.

KEM

The KEM registry covers the key-encapsulation mechanisms used to address a sealed payload to specific recipients. Label 309 registers a classical curve KEM and a post-quantum hybrid that ships active from the first release.

IdentifierAlgorithmPublic key / SecretCiphertext / Shared secret
x25519X25519 ECDH (RFC 7748)32 B / 32 B32 B / 32 B
mlkem768x25519X-Wing hybrid (ML-KEM-768 + X25519)1216 B / 32 B1120 B / 32 B

mlkem768x25519 is the X-Wing construction from the CFRG X-Wing draft: it pairs ML-KEM-768 with X25519 so that an attacker must break both to recover the shared secret. The public key is the ML-KEM-768 encapsulation key concatenated with the X25519 public key (1184 B ‖ 32 B = 1216 B); the secret is a 32-byte seed from which the full key is derived. Each recipient's ciphertext is the ML-KEM-768 ciphertext concatenated with an ephemeral X25519 public key (1088 B ‖ 32 B = 1120 B), and the two shared secrets are combined with SHA3-256 into the final 32-byte secret. The identifier is written without internal hyphens to match the established X-Wing spelling.

The hybrid is selected per-record by the encryption header, independently of the content AEAD. Because it is already registered, post-quantum confidentiality is a matter of choosing the identifier — not waiting for a new wire-format version.

KDF

The KDF registry names the key-derivation functions. hkdf-sha256 derives keys inside the sealed construction; argon2id stretches a human passphrase against brute force and carries a mandatory parameter floor.

IdentifierAlgorithmParameters
hkdf-sha256HKDF-SHA-256 (RFC 5869)salt (optional), info (optional), output length
argon2idArgon2id (RFC 9106)memory ≥ 65536 KiB, iterations ≥ 3, parallelism ≥ 1

The Argon2id floor is normative: a passphrase-protected payload MUST use at least 64 MiB of memory, at least three iterations, and at least one lane. A producer MAY choose stronger parameters, and they travel with the record so a verifier can reproduce the derivation.

Signature

Label 309 registers one signature algorithm. Authorship signatures are always optional, but when present they are carried as COSE_Sign1 (RFC 9052) using Ed25519.

IdentifierCOSE algAlgorithmWrapper
EdDSA-8Ed25519 (RFC 8032)COSE_Sign1 (RFC 9052)

Verification is strict per RFC 8032 §5.1.7: implementations MUST reject non-canonical signature encodings and small-order points (no cofactor-clearing extension). This matches the conservative acceptance criteria used across Cardano wallets, so a signature that verifies under one conformant implementation verifies under all of them.

Signature support is independent of the content claim. A verifier that does not implement a record's signature algorithm marks that signature slot as unsupported and leaves the timestamp and content claims fully valid — an unknown signature algorithm never invalidates the record itself.

Reserved identifiers

Several identifiers are named but not yet active. They mark the agreed migration path so that future profiles use stable, pre-committed names rather than ad-hoc strings. A conformant producer MUST NOT emit them, and a conformant verifier MUST reject any record that uses one, with the matching typed error.

IdentifierAlgorithmRole
aes-256-gcmAES-256-GCM (NIST SP 800-38D)Content AEAD
ml-kem-768ML-KEM-768 (FIPS 203), standaloneKEM
ml-dsa-65ML-DSA (FIPS 204)Signature
slh-dsa-sha2-128sSLH-DSA (FIPS 205)Signature

ml-kem-768 is the bare post-quantum KEM, distinct from the registered hybrid mlkem768x25519; the hybrid is what Label 309 ships, on the principle that a classical fallback should remain even after the post-quantum half is added.

Algorithm agility and migration

Adding an algorithm is a self-contained, additive operation: cite a public standard for the primitive, add the identifier to the appropriate registry, provide a vetted, well-reviewed implementation of it, and publish a cross-language conformance fixture so independent implementations agree byte-for-byte. The wire-format version does not change, because the schema does not change — only the set of recognized strings grows.

The consequences follow directly from the registry design:

  • Old records stay verifiable. Their identifiers are still in the registry, so every existing record verifies exactly as it did the day it was published.
  • Old verifiers fail closed. A verifier that predates a new identifier rejects records using it with a stable UNSUPPORTED_* error rather than guessing — there is no path to silent acceptance.
  • Post-quantum support is additive. Because mlkem768x25519 is already registered, and because new KEMs and signatures slot into the same mechanism, the post-quantum transition is a registry growth, not a breaking migration.

A wire-format version bump is reserved for genuinely breaking schema changes — a new required field, a removed field, a changed type. Registry growth never qualifies, which is precisely what lets the cryptographic catalogue evolve without ever stranding a published proof.