The Device List Is the Certificate: Post-Quantum Identity Proofs at a Fifth of the Size, Without Inventing Anything

by R. Demetri Vallejos
post-quantumagent-identityml-dsapkimerkle-tree-certificatesedge-aiaiossecurity

Every device in an Aethyr fleet carries a credential from its organization. It says three things: this device is ours, here is what it may do, and we signed this. The credential is a W3C Verifiable Credential, the signature is ML-DSA-65, and every connection starts with a server checking it. Presented on the wire, the credential token is 5,440 bytes.

Five kilobytes is invisible on a phone. On the embedded hardware we build toward, where a few hundred kilobytes of memory is the whole budget and the radio is the slowest thing on the board, it is a line item on every connection, and it grows every time the security bar rises. Per FIPS 204, an ML-DSA-65 public key is 1,952 bytes and its signature is 3,309. At ML-DSA-87 the signature alone is 4,627. The signature is three fifths of our credential. Everyone migrating identity to post-quantum signatures hits the same wall. The math holds. The bytes do not fit.

We cut our credential proof to 1,024 bytes. The design is borrowed, deliberately, from the most battle-tested tree structure in public-key infrastructure. This post covers what we built, where each piece comes from, and why the borrowing is the point.


The Public Web Is Hitting the Same Wall

On September 10, 2026, Cloudflare announced that its 1.1.1.1 resolver validates ML-DSA-44 DNSSEC signatures. Each signature is 2,420 bytes. RFC 9715 recommends keeping DNS-over-UDP responses under 1,400 bytes to avoid fragmentation, and many resolvers cap at 1,232, so a single ML-DSA-44 signature exceeds the budget before the response contains anything else. Cloudflare's guidance is that the authoritative server should return a truncated response and let the resolver retry over TCP. The cryptography deployed cleanly. The transport assumptions did not survive it.

The web PKI faces the larger version of the same problem. Let's Encrypt wrote in June that replacing the signatures in a certificate chain with ML-DSA would push a single TLS handshake well past ten kilobytes, and Cloudflare put the overhead at tens of kilobytes per handshake, enough to have a noticeable effect on TLS performance. The answer the industry is converging on is Merkle Tree Certificates. Cloudflare and Chrome have been running an experiment with MTCs against real traffic since late 2025. The IETF's PLANTS working group is standardizing the design as draft-ietf-plants-merkle-tree-certs. Chrome has named MTCs its preferred path for post-quantum certificates on the public web. Let's Encrypt is targeting late 2026 for a staging environment that issues them and 2027 for production.

The idea is simple. A certificate authority signs one tree head covering a batch of certificates. A relying party that already holds that tree head accepts a short inclusion proof in place of a signature chain. In the common case the whole authentication path is one signature, one public key, and one inclusion proof.

The hard part on the public web is distribution: getting trusted tree heads into every browser, every embedded TLS stack, every copy of curl. That is years of ecosystem work. A private fleet does not have that problem. We control both ends.


What We Built

The organization's commissioner already issues every device credential. Once a day it takes the active, unexpired credentials, strips the signature from each, and hashes what remains into a leaf. That content covers identity, key binding, and granted capabilities. The commissioner builds a Merkle tree over the leaves and publishes the head: a 32-byte root, the leaf count, the hash algorithm, and a seven-day expiry.

The head reaches servers two ways. The commissioner signs it with the same ML-DSA key it already uses to sign credentials, and a server accepts the head only after verifying that signature under a commissioner key it already holds. The tenant's anchors document, which every server loads and which already lists the commissioner keys and the revocation set, carries the current heads as well. There is no new signing key and no new trust anchor.

A device then fetches its inclusion proof and presents it in place of the signed credential.

FieldWhat it carries
ClaimsThe credential body, without its signature: identity, key binding, granted capabilities
HeadThe 32-byte root the device's leaf belongs to
SizeThe leaf count of that tree
IndexThe device's position among the leaves
LeafThe device's own leaf hash
PathThe sibling hashes from the leaf to the root, 32 bytes per level
Hash algorithmWhich of the two published trees this proof walks

The server checks that the claims hash to the leaf, that it holds an unexpired head from this commissioner with the same root, size, and hash algorithm, and that the path recomputes the root from the leaf. Then it is done. It never sees another device's credential.

On the wire, the numbers are:

TokenBytes
Full credential, ML-DSA-65 signature5,440
Full credential, ML-DSA-87 signature7,198
Inclusion proof, BLAKE3 tree, five-device roster1,024
Inclusion proof, SHA3-256 tree, five-device roster956

The proof grows by 32 bytes each time the fleet doubles. At a thousand devices the path is ten levels and the token is 1,250 bytes. The whole thing fits inside the 1,400-byte budget the DNS signature blew through.

A device enrolled after the most recent publish presents its full signed credential until the next head lands. The two paths coexist, and the roster only ever shrinks the common case.

Revocation stays a separate check. After membership succeeds, the server still asks whether the device has been pulled. The roster answers "was this device enrolled as of the last publish." The revocation set answers "is it allowed right now." Keeping those questions apart is what lets the roster be a snapshot without becoming a liability.


Three Decisions, None of Them New Cryptography

The leaf is the full credential content, permissions included. The proof carries everything a server needs to make an authorization decision, the same way an MTC carries the whole certificate body. The inclusion proof replaces the signature. It does not replace the claims. A bare membership bit would have forced a second round trip for the rest.

Two roots per publish, one per hash function. Servers inside a FIPS boundary cannot use BLAKE3 for a security decision. Every publish therefore emits a parallel SHA3-256 tree through the same code, and the head and the proof each carry a registry field naming which tree they belong to. A verifier configured for FIPS accepts only the SHA3-256 tree and rejects a BLAKE3 proof outright. The leaf and node tags are identical under both hashes, so the two trees differ only in the function.

Size and index are bound to a trusted head before the path is walked. RFC 6962 left inclusion-proof verification underspecified, and implementations diverged. RFC 9162 fixed that with an explicit algorithm in section 2.1.3.2 that walks the path using the leaf index and the tree size together. We implement that algorithm. Before the walk, the verifier rejects an index at or beyond the tree size, caps the tree size, and matches the proof's root, size, and hash algorithm against a head it already trusts. The path can only confirm a head the server chose, never introduce one.


Why We Invented Nothing

We could have announced a novel post-quantum enrollment tree. We chose not to. Certificate Transparency has run this exact structure at internet scale since 2013. The tree shape and the split rule, where a tree of n leaves splits at the largest power of two strictly less than n, come from RFC 6962. The verification algorithm comes from RFC 9162. The idea of presenting a proof against a batch head in place of a signature is the MTC draft's. Our wire specification cites each of them at the line where it applies.

What is ours is small and worth stating exactly. The hash function is BLAKE3 or SHA3-256 rather than SHA-256. The leaf and node domain separation uses short string tags that name the tree version and the leaf type, where Certificate Transparency uses a single prefix byte. The leaf content is the canonical JSON of the credential. None of that is a new construction. Domain-separated hashing is how every tree in this family is built. When a security reviewer asks what is new here, the answer is "nothing in the cryptography." That answer is the feature. Novel constructions need years of public scrutiny. Proven constructions need correct implementation, and correctness is something we can demonstrate.

We demonstrate it with one file of golden test vectors. The Rust reference implementation generates it, and its test suite asserts on every run that regenerating the file produces the committed bytes. The file holds sixteen cases: five that must be granted, across both signature levels and both hash trees, and eleven that must be rejected, one for each check in the verifier's order, including a BLAKE3 proof presented to a FIPS verifier and a proof whose head the server does not hold. The TypeScript implementation in our console is an independent reimplementation, and its tests replay all sixteen cases and the roster construction itself. Our node and our mesh link the Rust reference directly and replay the same file. An implementation that disagrees with the vectors does not build.


Where This Goes Next

The public web will spend years moving trust roots into clients. Private fleets, industrial systems, robots, and agents that already trust a single operator can run this design now. On constrained hardware, the size pressure of post-quantum signatures makes it a necessity.

The harder problem is the one no single operator solves. Our wire format is ours, but the credential is the boundary of the product. A visiting agent or robot will arrive with a credential we did not issue, shaped by the W3C Verifiable Credentials Data Model and the IETF's work on carrying ML-DSA signatures in COSE and JOSE. Our credential is already a Verifiable Credential in shape. Our next milestone makes its proof and its status format conformant with those specifications, so that one verification path answers the same four questions for a guest as for our own device. Is the identity real? Who vouches for it? Do the proofs hold? What does it grant?

The roster makes our own proofs small. Conformance makes everyone else's proofs readable. Both have to be true.

We will publish the wire specification and the vector files. If you are building post-quantum identity for a fleet you control, take the design. We did.


Aethyr Research, Salt Lake City, UT