| Internet-Draft | DRL TLS Stapling | July 2026 |
| Premont & Afifi | Expires 7 January 2027 | [Page] |
Managing certificate revocation remains a recurring challenge in the Web Public Key Infrastructure (WebPKI). Existing solutions such as Certificate Revocation Lists (CRLs) and the Online Certificate Status Protocol (OCSP) involve compromises in terms of propagation latency, availability, and user privacy. With the planned deprecation of OCSP by some major Certificate Authorities (CAs), there is renewed interest in alternatives.¶
This document specifies a decentralized certificate revocation architecture based on a Distributed Revocation Ledger (DRL) managed collectively by CAs. The ledger state is maintained as a Sparse Merkle Tree (SMT) in which only revoked certificates occupy non-default leaves, so that a valid certificate is attested by a compact non-membership proof and no prior registration of valid certificates is required. This document further defines a new Transport Layer Security (TLS) extension enabling "DRL Stapling", which allows a server to provide a client with a cryptographic proof of a certificate's status, consisting of a Sparse Merkle audit path and an M-of-N threshold signature from the CA consortium. The approach builds on the Revocation Transparency proposal of Laurie and Kasper and on subsequent formalizations of Sparse Merkle Trees; its novel contributions are the decentralized threshold-signature trust model with deterministic finality and the concrete TLS wire format.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 7 January 2027.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
The Web Public Key Infrastructure (WebPKI) relies heavily on the reliable dissemination of certificate revocation information. Standardized mechanisms show significant limitations:¶
To address latency and privacy, OCSP Stapling [RFC6066] was introduced, but it still relies on centralized OCSP infrastructure. Proprietary mechanisms like CRLite address privacy and availability but rely on a single trusted aggregator without distributed cryptographic proof.¶
This work is directly inspired by, and builds upon, the Revocation Transparency (RT) proposal of Laurie and Kasper [RevocationTransparency], which first proposed storing certificate revocation status in a Sparse Merkle Tree and stapling a recent proof alongside the certificate. It also builds on the subsequent formalization of Sparse Merkle Trees and their (non-)membership proofs by Dahlberg, Pulls, and Peeters [SMT]. RT deliberately left the trust model out of scope. The novel contribution of this document is twofold: (1) a decentralized trust model in which the ledger root is signed by an M-of-N threshold signature produced by a consortium of CAs operating a consensus with deterministic finality, replacing RT's reliance on an auxiliary transparency log for accountability; and (2) a concrete TLS wire format for stapling the resulting proof.¶
Because the ledger is a Sparse Merkle Tree in which only revoked certificates occupy non-default leaves, a valid certificate is proven by a compact non-membership proof, and CAs need not register valid certificates. The server fetches the proof from a local DRL node and staples it; the client verifies it as a purely local cryptographic operation.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The DRL is a Sparse Merkle Tree collectively maintained by participating CAs acting as consensus validators. Only revocations are inserted; a certificate that has never been revoked corresponds to a default (empty) leaf. The consortium signs the SMT root of each Epoch with a threshold signature.¶
While the exact ledger implementation is outside the scope of this TLS extension, the underlying network MUST guarantee:¶
Deterministic Finality: Once committed, a revocation cannot be reverted or forked. Proof-of-Work and probabilistic Proof-of-Stake are NOT RECOMMENDED; permissioned Byzantine Fault Tolerant (BFT) / Proof-of-Authority consensus is RECOMMENDED.¶
Authority Accountability: The validator set MUST consist of identifiable and accountable entities, such as CAs present in existing root trust stores.¶
When a CA revokes a certificate, it submits a signed revocation transaction. Upon consensus, the corresponding SMT leaf transitions from default to a revoked value, a new Epoch is finalized, and the validators produce a collective threshold signature over the new SMT root together with the epoch metadata. The following properties are RECOMMENDED for the underlying DRL protocol:¶
Note that, because only revocations are stored, no registration of valid certificates is required.¶
To limit latency and distribute load, DRL Nodes may be deployed close to
servers. (Edge topologies such as Multi-Access Edge Computing are one
possible non-normative realization.) A node holds a synchronized replica of
the SMT and computes, on demand, either a membership proof (for a revoked
certificate) or a non-membership proof (for a certificate absent from the
tree), attaching the consortium threshold signature for the current Epoch.
This yields the DRLProof.¶
The DRL is a Sparse Merkle Tree of depth D, where D equals the output length in bits of the tree hash algorithm (256 for SHA-256). Each certificate is mapped to a unique leaf whose position is the digest of its identifier. A valid (never-revoked) certificate maps to a default leaf; a revoked certificate maps to a non-default leaf carrying its revocation reason.¶
The leaf index for a certificate is computed as
leaf_index = Hash(CertificateID), where Hash is the
algorithm identified by hash_algo and CertificateID is
serialized as defined in Section 7.2. The index is
interpreted as a bit string b[0..D-1] with b[0] the most significant bit;
b[0] selects the direction at the root and b[D-1] at the leaf's parent.¶
To prevent second-preimage confusion between leaves, internal nodes, and empty subtrees, hashing employs distinct one-byte domain separation prefixes:¶
E[0] = Hash(0x00).¶
E[k] = Hash(0x01 || E[k-1] || E[k-1]).¶
RevokedLeaf = Hash(0x02 || reason_code), where
reason_code is a single byte.¶
Hash(0x01 || left_child || right_child).¶
The default digests E[0..D] are deterministic and MUST be precomputed by all implementations. Because empty subtrees share these digests, only the non-default siblings along a path need to be transmitted; the resulting SMT root is deterministic and history-independent.¶
This specification defines a DRLHashAlgorithm enumeration for the
SMT and leverages the SignatureScheme registry of TLS 1.3
[RFC8446] for the threshold signature. The tree depth D is
determined by the chosen hash algorithm.¶
All structures use the TLS presentation language [RFC8446].¶
The hash_algo field identifies the hash algorithm used for the
SMT. Values are defined in the "DRL Hash Algorithm" registry established by
this document (Section 13).¶
enum {
sha256(1), /* D = 256 */
sha384(2), /* D = 384 */
sha512(3), /* D = 512 */
(255)
} DRLHashAlgorithm;
¶
Implementations MUST support sha256(1). Support for
sha384(2) and sha512(3) is RECOMMENDED.¶
enum {
valid(0), /* proven by a non-membership proof */
revoked(1), /* proven by a membership proof */
(255)
} CertificateStatus;
enum {
unspecified(0),
keyCompromise(1),
cACompromise(2),
affiliationChanged(3),
superseded(4),
cessationOfOperation(5),
certificateHold(6),
/* 7 reserved; 8 (removeFromCRL) intentionally omitted */
privilegeWithdrawn(9),
aACompromise(10),
(255)
} CRLReason;
struct {
opaque issuer_hash<32..64>;
opaque serial_number<1..32>;
} CertificateID;
¶
The CRLReason values are drawn from
[RFC5280] Section 5.3.1; removeFromCRL(8) is omitted
as it pertains to delta-CRL processing.¶
issuer_hash: the hash of the DER-encoded Subject Public Key
Info (SPKI) of the issuer's certificate, using hash_algo; its
length MUST equal the output length of that algorithm (32, 48, or 64
bytes).¶
serial_number: the raw value bytes of the ASN.1 INTEGER
serial number (without tag/length), in network byte order. Formatting
characters (e.g., ':') MUST NOT be used.¶
The canonical serialization of CertificateID is its
TLS-presentation-language encoding per [RFC8446] Section 3,
with length-prefixed opaque vectors. The leaf index is computed
over exactly these bytes.¶
A DRL Proof carries everything the client needs to recompute the SMT root
and evaluate the status. The audit path transmits only non-default
siblings; a bitmap indicates, for each of the D levels (bottom to top),
whether the sibling is non-default (present in audit_path) or is the
precomputed default digest for that level.¶
struct {
opaque node_hash<20..64>;
} MerkleNode;
struct {
CertificateID cert_id;
CertificateStatus status;
CRLReason reason_code; /* meaningful only if status == revoked */
DRLHashAlgorithm hash_algo;
SignatureScheme sig_scheme;
opaque key_id<4..32>;
opaque path_bitmap<0..2^16-1>; /* D bits, ceil(D/8) bytes, bit j = level j */
MerkleNode audit_path<0..2^16-1>; /* non-default siblings, bottom to top */
uint64 epoch_number;
uint64 epoch_timestamp;
opaque root_signature<1..2^16-1>;
} DRLProof;
¶
status: valid(0) denotes a non-membership proof (the
leaf at leaf_index is empty); revoked(1) denotes a
membership proof (the leaf holds RevokedLeaf).¶
path_bitmap: exactly ceil(D/8) bytes. Bit j (j = 0 is the
bottom/leaf level) set means the sibling at level j is non-default and
appears next in audit_path; unset means the sibling is the
default digest E[j].¶
audit_path: the non-default siblings in bottom-to-top order,
in the same order as the set bits of path_bitmap.¶
key_id: identifier of the consortium aggregated public
threshold key, computed as the leading 20 bytes of the SHA-256 hash of the
serialized aggregated public key. If unrecognized, the client MUST reject
the proof.¶
epoch_number: strictly monotonically increasing 64-bit epoch
counter; ensures ordering, uniqueness, and rollback detection.¶
epoch_timestamp: UNIX timestamp (seconds) of epoch
finalization, used for freshness.¶
root_signature: the M-of-N threshold signature over
ComputedRoot || epoch_number || epoch_timestamp, with the two
integers encoded as 8 bytes each in network byte order.¶
To ensure interoperability in the absence of a standardized threshold
signature code point, implementations MUST support a baseline mode in which
root_signature carries the concatenation of individual
SignatureScheme signatures (using a mandatory-to-implement scheme
such as ecdsa_secp256r1_sha256), of which at least M MUST verify
against consortium member keys in the client's trust store. BLS threshold
aggregation, following [I-D.irtf-cfrg-bls-signature], is an
OPTIONAL optimization; once an IANA code point is assigned it MUST be used in
sig_scheme. Any threshold scheme used MUST prevent rogue-key
attacks.¶
We define a new Certificate Status Type for the status_request
extension [RFC6066].¶
enum {
ocsp(1),
drl_proof(TBD),
(255)
} CertificateStatusType;
¶
A client wishing to receive a DRL Proof includes a
status_request extension with status_type set to
drl_proof. A client MAY advertise both drl_proof and
ocsp.¶
If the server holds a valid DRLProof for its end-entity
certificate and the client advertised drl_proof, the server MUST
include the DRLProof in the CertificateStatus structure.
In TLS 1.3 [RFC8446] it is carried in the extensions
of the relevant CertificateEntry; in TLS 1.2 it follows
[RFC6066] in a CertificateStatus message. The server
MUST NOT send an empty drl_proof status; it MAY fall back to
ocsp.¶
drl_proof but
receives none, it SHOULD apply its local revocation policy.¶
Upon receiving a DRLProof, the client MUST perform the following
steps. If any fails, the proof is invalid. The client MUST NOT act on
status until steps 1 through 5 succeed, to prevent an attacker from
forcing a handshake abort via an unauthenticated revoked claim.¶
Identifier and index: Verify that cert_id
matches the server certificate (issuer SPKI hash and serial number), then
compute leaf_index = Hash(cert_id) using hash_algo.¶
Leaf digest: If status is valid,
set cur = E[0]. If revoked, set
cur = Hash(0x02 || reason_code).¶
Root reconstruction: For j from 0 to D-1: let the
controlling bit be b[D-1-j] of leaf_index; obtain the
sibling S = audit_path next entry if path_bitmap bit j is
set, else S = E[j]. If the controlling bit is 0, set
cur = Hash(0x01 || cur || S); else
cur = Hash(0x01 || S || cur). After D iterations,
ComputedRoot = cur. Implementations MUST verify that the number of
set bits in path_bitmap equals the number of entries in
audit_path.¶
Signature: Look up the aggregated key for
key_id; if absent, reject. Verify root_signature using
sig_scheme over
ComputedRoot || epoch_number || epoch_timestamp. It MUST be a valid
M-of-N threshold signature.¶
Freshness: epoch_timestamp MUST be within
the acceptable freshness window; stale proofs MUST be rejected. Stateful
clients MAY reject proofs whose epoch_number is lower than the
highest previously seen.¶
Status evaluation: If status is
revoked, abort with a certificate_revoked alert.¶
The client performs no outbound status query, so browsing habits and IP
address are never exposed to third-party responders. For SHA-256 (D = 256),
the average number of non-default siblings on a path is O(log N) where N is
the number of revoked certificates [RevocationTransparency]
[SMT]; the remaining siblings are default and omitted, kept
implicit via path_bitmap.¶
Servers SHOULD refresh their cached DRLProof at an interval shorter
than the client freshness window (a RECOMMENDED value is half the window), with
exponential-backoff retry. The consortium SHOULD generate epochs at a regular
cadence; for Web PKI, an epoch interval between 1 minute and 1 hour is
RECOMMENDED.¶
Security relies on the assumption that compromised authorities do not exceed the fault-tolerance threshold f (typically M = 2f + 1 with N = 3f + 1). Unlike OCSP, a single compromised CA cannot forge a root signature; an adversary must compromise M authorities to subvert the system. This replaces the auxiliary-log accountability of Revocation Transparency with cryptographic threshold accountability.¶
Because the SMT represents a mutable current state, an evil node could
attempt to present a stale root in which a currently revoked certificate
still appears valid, as described in
[RevocationTransparency]. The epoch_number and
epoch_timestamp strictly couple the signature to one epoch. Clients
MUST enforce a freshness threshold and therefore MUST maintain a reasonably
accurate clock; stateful clients SHOULD additionally enforce monotonicity of
epoch_number to detect rollback and equivocation.¶
Distinct domain separation prefixes for empty leaves, revoked leaves, and
internal nodes prevent an interior digest from being reinterpreted as a leaf,
following the encoding rationale of [SMT]. Because the tree
depth is fixed by hash_algo, the position of a leaf is uniquely
determined by Hash(cert_id), binding a revocation to its
certificate.¶
A partitioned DRL Node freezes at an old epoch. Servers SHOULD fail over to an alternative node; otherwise clients reject the stale proof once the freshness threshold expires, providing a fail-safe.¶
This specification assumes a functioning CA consortium willing to operate validators and produce threshold signatures. Establishing such a consortium (membership, liability, key-share custody, edge funding) is a governance problem out of scope here and is expected to require coordination with root program operators and the CA/Browser Forum.¶
Clients are provisioned with the consortium aggregated public key via
their trust store, analogous to a root CA. Each key is identified by
key_id (leading 20 bytes of SHA-256 of the serialized key). On
membership changes, a new key is distributed; during a transition period the
consortium signs each root with both old and new keys, and clients accepting
either key_id validate either proof. After the transition, the old
key is retired.¶
IANA is requested to assign a new value for drl_proof in the
"TLS Certificate Status Types" registry [RFC6066].¶
| Value | Description | Reference |
|---|---|---|
| TBD | DRL Sparse Merkle Proof | This document |
IANA is requested to create a "DRL Hash Algorithm" registry with a "Specification Required" policy.¶
| Value | Description | Reference |
|---|---|---|
| 0 | Reserved | This document |
| 1 | sha256 | This document |
| 2 | sha384 | This document |
| 3 | sha512 | This document |
| 4-254 | Unassigned | |
| 255 | Reserved | This document |
This non-normative example uses a toy depth of D = 4 for readability
(a real deployment uses D = 256 for SHA-256). Suppose the certificate maps to
leaf_index = 1011 (b[0]=1, b[1]=0, b[2]=1, b[3]=1) and is
valid, i.e., its leaf is empty.¶
Precompute defaults:
E[0] = Hash(0x00)
E[1] = Hash(0x01 || E[0] || E[0])
E[2] = Hash(0x01 || E[1] || E[1])
E[3] = Hash(0x01 || E[2] || E[2])
Start (status = valid):
cur = E[0]
Walk bottom (j=0) to top (j=3); controlling bit = b[3-j]:
j=0: bit b[3]=1 -> cur is right child.
sibling S0 = (bitmap bit0 set ? audit_path[.] : E[0])
cur = Hash(0x01 || S0 || cur)
j=1: bit b[2]=1 -> cur is right child.
cur = Hash(0x01 || S1 || cur)
j=2: bit b[1]=0 -> cur is left child.
cur = Hash(0x01 || cur || S2)
j=3: bit b[0]=1 -> cur is right child.
cur = Hash(0x01 || S3 || cur)
ComputedRoot = cur
Verify root_signature over
(ComputedRoot || epoch_number || epoch_timestamp)
using the consortium aggregated key selected by key_id,
then check freshness. Since status = valid, the handshake proceeds.
¶