Internet-Draft ACME PK Challenge June 2026
Geng, et al. Expires 16 December 2026 [Page]
Workgroup:
Automated Certificate Management Environment Working Group
Internet-Draft:
draft-geng-acme-public-key-07
Published:
Intended Status:
Standards Track
Expires:
Authors:
F. Geng
Huawei Technologies
P. Wu
Huawei Technologies
L. Xia
Huawei Technologies
X. Chen
TrustAsia

Automated Certificate Management Environment (ACME) Extension for Public Key Challenges

Abstract

The Automatic Certificate Management Environment (ACME) [RFC8555] requires a PKCS#10 Certificate Signing Request (CSR) at the finalization stage. This document defines a new ACME challenge type, "pk-01", that allows a client to prove possession of a private key directly, without constructing a CSR. The primary motivation is to support key types that cannot generate CSR self-signatures, notably post-quantum Key Encapsulation Mechanism (KEM) keys. The client declares the public key via a popKey field in the "newOrder" request; the server attaches the "pk-01" challenge to existing identifier authorizations. When all required authorizations are satisfied, the ACME server issues a certificate using the validated public key and the authorized identifiers, eliminating the need for a CSR in the finalization stage.

Status of This Memo

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 16 December 2026.

Table of Contents

1. Introduction

1.1. Background and Motivation

In the current ACME flow, the applicant submits a PKCS#10 [RFC2986] CSR at the finalization stage. The CSR carries both the certificate public key and a self-signature over the CSR contents; the former is used for certificate issuance, while the latter serves as a proof of possession for the public key. Actually, it merely indicates that someone wanted to associate this key with these domain names at a certain time, the signature in CSR is not proof of key possession.

This extension enables CSR-less certificate issuance. It is important to be precise about the motivations:

  • Primary motivation: KEM-only keys. Key-encapsulation mechanisms (such as ML-KEM [FIPS-203]) cannot produce digital signatures. This is a hard cryptographic constraint, not a mere inconvenience. Protocols that use KEM public keys for authentication or encryption (e.g., KEMTLS) require a certificate issuance path that does not assume signature-capable keys. Without a mechanism like "pk-01", automated certificate management for these key types is impossible.

  • Secondary motivation: eliminating client-side ASN.1/DER encoding. Constructing a valid PKCS#10 CSR requires an ASN.1/DER encoding toolchain. For resource-constrained devices, this adds code complexity. However, many devices that can perform TLS handshakes and JWS signatures already have sufficient resources for CSR generation. The elimination of CSR is therefore a convenience, not a necessity, for most deployments.

This document does not claim that CSR is fundamentally broken or that the PKCS#10 format is inherently problematic. The CSR self-signature mechanism has served the Internet well for decades. The "pk-01" challenge exists primarily because post-quantum cryptography introduces key types that are incompatible with that mechanism.

1.1.1. Use Cases and Deployment Scenarios (Informative)

The design described in this document is motivated by concrete deployment scenarios. The value of Proof-of-Possession (PoP) varies significantly across these scenarios, and implementers should understand which benefits apply to their use cases.

  • KEM-Only Public Keys (Post-Quantum and Beyond). This is the primary use case. Without "pk-01", automated certificate management for KEM keys is impossible. The security value of PoP here is absolute: it is the only way to prove possession.

  • Resource-Constrained Devices (IoT). Microcontrollers and deeply embedded systems benefit from the elimination of ASN.1/DER encoding. For these devices, "pk-01" reduces code complexity. However, the security value of PoP in this scenario is identical to that of CSR-based PoP, only the implementation cost differs.

  • Composition of Identity and Key Attestation. In environments where a CA must validate both device identity (e.g., via hardware attestation) and private key possession, "pk-01" allows these two orthogonal assertions to be verified independently. This is the scenario where PoP provides the greatest security value beyond the KEM use case, because it prevents a device that passes identity checks from using a key it does not control.

  • Escrowed Encryption Keys. In some cryptographic infrastructures, encryption private keys are centrally escrowed by a Key Management Centre (KMC). The KMC acts as a proxy holding the private key on behalf of the client. When applying for an encryption certificate, the KMC must prove possession of the escrowed key. "pk-01" enables this without requiring the KMC to construct a CSR for each certificate.

  • Proxy Certificate Management (Enterprise Network Management Scenario). In enterprise environments, a Network Management System (NMS) may act as a proxy to request certificates on behalf of end devices that are resource-constrained or do not run an ACME client natively. The PoP mechanism of "pk-01" ensures that even when an order is initiated by a proxy, the private key holder (the end device) must be online to complete the proof. A proxy cannot pass the challenge without assistance from the device’s private key. When used together with device-attest-01, the CA can further verify that the public key contained in popKey originates from a trusted device, rather than a key generated by the proxy.

For standard DNS-based Web PKI certificate issuance, where the applicant proves domain control via dns-01 or http-01, the additional security provided by PoP — whether via CSR or "pk-01" — is marginal. An attacker who can pass domain control challenges can simply generate their own key pair and prove possession of it. The primary security function of PoP in this context is to ensure that the certified public key is well-formed and corresponds to a private key the applicant actually holds, which prevents accidental misconfiguration rather than active attacks.

1.2. Scope

This document defines:

  • A new field popKey in the "newOrder" request, through which the client declares the public key to be certified.

  • A new ACME challenge type: "pk-01", which can be included in authorizations for any identifier type.

  • Two proof-of-possession modes within the challenge: one for signature keys and the other for KEM keys.

  • A finalization stage that omits the CSR when all required authorizations contain a valid "pk-01" challenge.

Identifier-control validation (for DNS names, email addresses, etc.) continues to be performed by existing ACME challenge types (dns-01, http-01, tls-alpn-01, email-reply-00, etc.); the "pk-01" challenge solely proves private key possession. This extension does not modify, overload, or replace any existing challenge type.

Scope limitation regarding application‑level use of KEM certificates:
This document defines a mechanism to issue X.509 certificates containing KEM public keys (e.g., ML‑KEM) and to prove possession of the corresponding private keys. However, the use of such certificates in application protocols (including TLS 1.3, S/MIME, and others) is not defined by this document and requires separate standardization. Implementers and deployers should not assume that KEM certificates will work in existing protocol stacks without further updates. This draft provides the necessary infrastructure; the application‑level integration is left for future work.

1.3. Relationship to Other ACME Extensions

This extension is designed to be used orthogonally with several ongoing ACME working group efforts. Implementers and deployers should note the following relationships:

  • Device Attestation (acme-device-attest): Device attestation establishes the identity and trusted state of a device itself, typically using hardware-backed attestation evidence (e.g., TPM quotes). The "pk-01" challenge addresses a different layer: it proves that the requester holds the private key corresponding to the public key to be certified. In a device-certificate enrollment scenario, these two mechanisms complement each other: device attestation confirms which device is requesting a certificate, while "pk-01" confirms that the device actually controls the keypair that will be bound to that certificate. An authorization may contain both a device-attestation challenge and a pk-01 challenge; their validations are independent, and the CA's issuance policy can require both to succeed.

  • Remote Attestation (acme-rats): Similar to device attestation, remote attestation procedures evaluate the security posture of the requesting environment. "pk-01" does not duplicate or replace these mechanisms; it provides a pure PoP primitive that can be composed with attestation-based authorizations to satisfy comprehensive certificate enrollment policies.

  • ACME Profiles (acme-profiles): When a certificate's subject and SAN are not fully determined by identifiers (e.g., if only a "pk-01" challenge is used without other identifiers – see CA policy), clients MAY use the profiles extension [I-D.aaron-acme-profiles] to express preferences for how the CA should populate those fields.

1.4. Relationship to Prior IETF Work on Proof-of-Possession

This document builds on several established IETF standards:

  • JOSE Unencoded Payload [RFC7797]: To avoid JSON serialization ambiguities, "pk-01" binds the proof to the raw newOrder JWS payload (the exact bytes received) rather than a re-serialized JSON object. This follows the precedent of using the "on-the-wire" representation for cryptographic operations.

  • Proof-of-Possession Key Semantics [RFC7800] [RFC8747]: This RFC formalized the notion of a PoP key bound to a security token. In this document, the public key carried in the popKey field and the "pk-01" challenge is a PoP key, and the ACME order is the binding context. Successful completion of the "pk-01" challenge proves that the client holds the private key corresponding to this PoP key.

  • OAuth 2.0 DPoP [RFC9449]: Demonstrates an application-layer PoP mechanism using server-generated nonces and context binding. In the ACME framework, "pk-01" can be viewed as an analogue of DPoP: it proves possession of the certificate key bound to an ACME order. DPoP's successful deployment in production environments confirms the viability and security of such application-layer PoP mechanisms. However, unlike DPoP (where individual requests are short-lived and failures are cheap), certificate issuance is a high-cost and non-ephemeral operation. ACME's challenge/authorization state machine provides a natural place to perform PoP validation before the order becomes "ready", so that finalization remains an atomic, deterministic step. Embedding PoP validation into the authorization phase is therefore a deliberate engineering decision that leverages ACME's existing infrastructure, rather than introducing a separate, decoupled proof submission mechanism.

1.5. Protocol Overview

The following diagram provides a high-level overview of the "pk-01" protocol interaction. It illustrates the complete lifecycle from the client's initial "newOrder" request through certificate issuance, covering both the server capability discovery phase and the parallel execution of identifier-control challenges alongside the "pk-01" proof-of-possession challenge.

CLIENT                                      SERVER
   |                                          |
   |--- (0) GET /directory ------------------>| // Discover server capabilities
   |<-- {..., popSupported: true} ------------|
   |                                          |
   |--- (1) POST /newOrder ------------------>| // Declare identifiers + popKey
   | { identifiers: [dns: example.com],       |
   | popKey: <SPKI> }                         |
   |                                          | // Validate popKey, create order
   |                                          | // Attach "pk-01" to authorization(s)
   |                                          |
   |<-- (2) order { status: "pending",        |
   | authorizations: [                        |
   | { challenges: [                          |
   |    dns-01: {token},                      |
   |    pk-01: {key: <SPKI>,                  |
   |            popNonce | ciphertext}        |
   |    ]}                                    |
   | ],                                       |
   | popKeyAccepted: true }                   |
   |                                          |
   +---- Parallel Challenge Responses --------+
   |                                          |
   |(3a) Complete dns-01                      |
   |(3b) Compute PoP proof & POST /chall/pk01 |
   +------------------------------------------+
   |                                          |
   |[All challenges valid -> status: ready]   |
   |--- (4) POST /order/xyz/finalize {} ----->| // CSR-less finalization
   |<-- (5) certificate ----------------------|
   |                                          |
Figure 1: High-level overview of the "pk-01

Diagram Legend:

  • (0) Capability Discovery: The client queries the server's Directory metadata to determine "pk-01" support before initiating an order. If popSupported is absent or false, the client falls back to standard CSR-based ACME.

  • (1) Order Creation: The client declares both the identity identifiers (e.g., DNS name) and the certificate public key (popKey) in the "newOrder" request.

  • (2) Authorization Response: The server returns authorizations containing standard identifier-control challenges (e.g., dns-01) alongside the "pk-01" challenge. The "pk-01" challenge object contains either a nonce (for signature keys) or a challenge_ciphertext (for KEM keys).

  • (3a) Identifier Control: The client completes the standard challenge(s) to prove control of the requested identifiers.

  • (3b) Proof-of-Possession: In parallel, the client constructs the cryptographic proof for the "pk-01" challenge and submits it to the challenge URL. The server validates the proof and transitions the challenge state accordingly.

  • (4) Finalization: Once all challenges are valid, the order becomes ready. The client sends an empty {} finalize request, signalling that no CSR is required.

  • (5) Certificate Issuance: The server issues the certificate using the authorized identifiers and the validated public key from popKey.

1.6. Design Philosophy: What pk-01 Is and Is Not

The "pk-01" challenge serves one purpose: proving that the applicant possesses the private key corresponding to a declared public key. It is intentionally minimal. Several design choices derived from the following philosophy.

  • It is a challenge, not a new protocol layer. This reuses ACME's existing authorization state machine, error handling, and finalization gating. The Working Group discussed alternative designs (e.g., a separate PoP endpoint, a reusable PoP token). These alternatives offer architectural cleanliness at the cost of additional protocol complexity. This document chooses the pragmatic path of integration over abstraction. Future extensions may revisit this choice.

  • It does not replace CSR for all use cases. Clients that already have CSR generation capabilities and are using signature keys may continue to use the standard CSR-based flow. "pk-01" is not a deprecation of CSR.

  • It does not solve KEM certificate revocation. The inability of KEM keys to sign revocation requests is a cryptographic limitation, not a protocol deficiency. Section 7.5 discusses this honestly.

1.7. Server Capability Advertisement

An ACME server that supports the "pk-01" challenge SHOULD advertise this capability in its Directory metadata, so that clients can determine support before initiating an order:

{
  "newNonce": "https://acme.example.com/acme/new-nonce",
  "newAccount": "https://acme.example.com/acme/new-acct",
  "newOrder": "https://acme.example.com/acme/new-order",
  "meta": {
    "popSupported": true
  }
}

The popSupported field, located inside the "meta" object, is a boolean. If true, the server supports the "pk-01" challenge type and the popKey field in newOrder requests. If absent or false, the server does not support "pk-01", and clients SHOULD NOT include popKey in their requests. This allows clients to avoid unnecessary popKey submissions and to choose a compatible CA upfront when CSR-less operation is required. Clients SHOULD NOT assume that a server advertising popSupported: true fully implements this specification. If a client encounters behavior that violates the requirements of this document (e.g., a server ignoring popKey despite advertising support), it SHOULD report the incompatibility to the server operator and fall back to standard CSR-based ACME. The server MUST maintain support for "pk-01" throughout the entire lifetime of any order that includes "pk-01" challenges. If "pk-01" support is disabled while there are outstanding orders containing "pk-01" challenges, those orders MUST be immediately transitioned to the invalid state with an appropriate error description.

2. Conventions and Definitions

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.

This document uses the following terminology:

3. Declaring the Public Key: the popKey Field

3.1. The popKey Field in newOrder

Clients SHOULD use the popKey/pk-01 flow when they possess key types that cannot produce CSR self-signatures (e.g., KEM keys). Clients that already have CSR generation capabilities and are using signature keys may continue to use the standard CSR-based flow described in [RFC8555].

A client that wishes to use the CSR-less flow declares the public key to be certified by including a popKey field in the "newOrder" request:

POST /acme/new-order HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json
{
  "identifiers": [
      { "type": "dns", "value": "example.com" }
  ],
  "popKey": "<base64url(DER-encoded SPKI)>"
}

Field description:

  • popKey (OPTIONAL): The Base64URL encoding (without padding) of the DER-encoded SubjectPublicKeyInfo (SPKI) [RFC5480] of the public key to be certified.

The popKey field is not an identifier. It does not appear in the identifiers array and does not create a separate authorization. It is purely a declaration of the public key for which the client intends to prove possession.

3.2. Server Processing of popKey

Upon receiving a "newOrder" request with a popKey field, the server:

  1. MUST validate that the popKey value decodes to a well-formed SPKI conforming to [X.690] Section 11 distinguished encoding (strict DER), and that it contains no non-Base64URL characters or whitespace.

  2. MUST verify that the AlgorithmIdentifier in the SPKI corresponds to an algorithm listed in Section 5.1 (signature keys) or Section 5.2 (KEM keys). If the algorithm is not supported or the key parameters (e.g., RSA modulus length) do not meet the CA's policy, the server MUST return a urn:ietf:params:acme:error:badPublicKey error with a detail field describing the incompatibility (e.g., "RSA key length 2048 is below the required minimum of 3072").

  3. MUST verify that the public key in popKey differs from the account public key of the ACME account placing the order. If they are identical, the server MUST reject the request with urn:ietf:params:acme:error:badPublicKey (consistent with the considerations on separating certificate keys from account keys in [RFC8555] Section 11.1).

  4. If validation fails for any reason, the server MUST reject the "newOrder" request with error type urn:ietf:params:acme:error:badPublicKey.

  5. If validation succeeds, the server MUST store the SPKI bytes as received and associate them with the order.

  6. When creating authorizations for the order, the server MUST include a "pk-01" challenge in each authorization. The key field of each "pk-01" challenge MUST be byte-identical to the validated popKey value.

If the server does not support "pk-01", it MUST reject the request with a new error type urn:ietf:params:acme:error:popNotSupported (see Section 8.4). There is no silent fallback. This is a deliberate design choice to avoid ambiguous protocol states. Clients that require CSR-less operation should select a CA that advertises popSupported: true.

If the server receives a newOrder without a popKey and the server's policy requires PoP (e.g., for a specific account), the server MUST reject the order with a popNotSupported or a popKeyRejectedByPolicy error (if the server otherwise supports pk-01 but the account lacks permission). Servers MUST NOT silently assume knowledge of the client's public key through out-of-band means; the PoP flow is initiated solely by the client providing popKey.

3.3. Order Object Echo of popKey

The server MUST include the accepted popKey value and a popKeyAccepted field set to true in the order object when it intends to attempt using "pk-01":

{
  "status": "pending",
  "identifiers": [
    { "type": "dns", "value": "example.com" }
  ],
  "authorizations": [
    "https://acme.example.com/acme/authz/abc123"
  ],
  "popKey": "<base64url(DER-encoded SPKI)>",
  "popKeyAccepted": true,
  "finalize": "https://acme.example.com/acme/finalize/xyz"
}

The presence of popKeyAccepted: true indicates that the server has recorded the public key and will attempt to create the necessary pk-01 challenges; it does not guarantee that the order will eventually succeed (e.g., later authorization creation may fail). Clients MUST continue to monitor the order status and handle failures as usual.

A server implementing this specification never "ignores" popKey: it either accepts it and uses "pk-01" (popKeyAccepted: true), or rejects the order with popNotSupported (see Section 3.2). A legacy server that does not implement this specification will silently ignore popKey per [RFC8555]'s treatment of unrecognized fields, and the order object it returns will not contain a popKeyAccepted field. Clients MUST therefore treat the absence of the popKeyAccepted field in the order object as an indication that the server did not process popKey, and either fall back to CSR-based finalization or abandon the order.

If the server later discovers that it cannot attach pk-01 challenges to all required authorizations (e.g., due to identifier type incompatibility), it MUST transition the order to invalid with an appropriate error (e.g., malformed or unsupportedIdentifier). The popKeyAccepted field, once set to true, is not changed; clients rely on the order status to detect final outcome.

The client can use this field to confirm that the server correctly received the public key and intends to use pk-01. The server MUST ensure that the echoed popKey (when popKeyAccepted is true) is byte-identical to the value received in the "newOrder" request.

When a client detects that the server did not process popKey (no popKeyAccepted field in the order object), the client SHOULD cache this information for the duration of the ACME session or account lifetime, and SHOULD NOT include popKey in subsequent "newOrder" requests to the same server. The client MAY clear this cache if it detects a change in the popSupported field of the server's directory object.

4. The pk-01 Challenge

4.1. Attachment to Authorizations

An ACME server that has received a valid popKey in the "newOrder" request includes a "pk-01" challenge in one or more authorization objects returned for the order. The presence of the challenge signals that the server intends to use the validated public key for certificate issuance and will not accept the CSR at finalization.

If the order contains multiple authorizations (e.g., for different identifier types), and the server's policy requires PoP for this order, the server MUST include a "pk-01" challenge in all authorizations associated with the order. All such "pk-01" challenges MUST carry the same public key (matching the popKey). This symmetric treatment prevents any timing or processing-order vulnerabilities and keeps the authorization state model consistent.

An authorization containing a "pk-01" challenge is bound to a specific order's popKey and newOrder_hash. The authorization reuse permitted by [RFC8555] Section 7.1.4 therefore does not apply to such authorizations: the server MUST NOT associate an authorization containing a "pk-01" challenge (regardless of its state) with any other order, and MUST create fresh authorizations with fresh "pk-01" challenges for every new order that includes a popKey.

The "pk-01" challenge expires along with its containing authorization. If the authorization expires, the "pk-01" challenge MUST be automatically transitioned to invalid.

4.2. Challenge Object Fields

The "pk-01" challenge appears inside an authorization's challenges array. The set of fields in the challenge object depends on whether the key is a signature key or a KEM key, as determined by the server from the key field (which mirrors the popKey).

4.2.1. Challenge Object for Signature Keys

{
  "type": "pk-01",
  "url": "https://acme.example.com/acme/chall/abc123",
  "status": "pending",
  "key": "<base64url(DER-encoded SPKI)>",
  "popNonce": "Kz3mVpQeRd9fLwYbN5hXuT6oJsIc0vAg2nEp1yMrFqZ"
}

Field descriptions:

  • type: Fixed value "pk-01".

  • url, status: Per [RFC8555] Section 7.1.5 standard semantics.

  • key (REQUIRED): The Base64URL encoding (without padding) of the DER-encoded SubjectPublicKeyInfo (SPKI) of the public key to be certified. This value MUST be byte-identical to the popKey provided by the client in the "newOrder" request. While the key field is always identical to the popKey, it provides a useful consistency check in multi-authorization orders: the client can verify that all authorizations reference the same public key without having stored the popKey separately.

  • popNonce (REQUIRED for signature keys, mutually exclusive with challenge_ciphertext): A random value generated by the ACME server independently for this challenge, Base64URL-encoded, with at least 128 bits of entropy [RFC4086]. The nonce MUST be generated using a Cryptographically Secure Pseudorandom number Generator (CSPRNG) as specified in [RFC4086], preferably one compliant with NIST SP 800-90A. The same nonce MUST NOT be used for multiple challenges.This field is named popNonce to avoid confusion with the Replay-Nonce HTTP header and the nonce parameter in the JWS protected header used for anti-replay in ACME.

4.2.2. Challenge Object for KEM Keys

{
  "type": "pk-01",
  "url": "https://acme.example.com/acme/chall/def456",
  "status": "pending",
  "key": "<base64url(DER-encoded SPKI)>",
  "challenge_ciphertext": "Af2x3..."
}

Field descriptions:

  • type, url, status, key: Same as above.

  • challenge_ciphertext (REQUIRED for KEM keys, mutually exclusive with nonce): The Base64URL encoding of the ciphertext produced by the server's KEM Encapsulate operation using the public key from the key field. The KEM algorithm used is uniquely determined by the AlgorithmIdentifier in the SPKI (see Section 5.2).

  • kdf_version (OPTIONAL, integer): Indicates the version of the KDF (Key Derivation Function) used to derive mac_key from the shared secret. When absent, the value defaults to 1, which corresponds to the construction specified in Section 5.2 (HKDF-Extract with empty salt, HKDF-Expand with info "ACME-pk-01-KEM v1"). If a future version of this specification defines a different KDF, a client or server supporting that version MUST use the corresponding kdf_version value. The presence of this field allows protocol evolution without creating a new challenge type.

The nonce and challenge_ciphertext fields are mutually exclusive: each "pk-01" challenge object MUST contain exactly one of them. The server determines which field to use based on the key type declared in the key field.

4.3. Multiple pk-01 Challenges in an Order

As stated in Section 4.1, an order containing multiple authorizations MUST include a "pk-01" challenge in each authorization when the server requires PoP. All such challenges MUST carry the same key value (byte-identical SPKI). The server MUST verify this consistency at the time the authorizations are created. If the server's policy requires PoP, and it cannot create consistent "pk-01" challenges across all authorizations (e.g., because different authorization types have different challenge templates), the server MUST reject the newOrder request. As an additional safeguard, the server SHOULD re-verify consistency before transitioning the order to ready.

All required challenges (both identifier-control and pk-01) MUST reach the valid state before the order transitions to ready. If any "pk-01" challenge in any authorization transitions to invalid, the entire order MUST be immediately transitioned to invalid, regardless of the state of other challenges.

5. Proof-of-Possession Execution

5.1. PoP for Signature Keys

In signature key mode, the "pk-01" challenge object contains the nonce field. The applicant constructs the proof as follows:

1) Let raw_newOrder be the exact JSON payload bytes of the "newOrder" request.

2) Compute newOrder_hash = SHA-256(raw_newOrder).

3) Let popNonce_bytes be the raw bytes obtained by Base64URL-decoding the nonce field.

4) Construct the message to be signed:

to_sign = "ACME-pk-01-sig v1:" || popNonce_bytes || newOrder_hash

where || denotes raw byte concatenation and "ACME-pk-01-sig v1:" is a fixed 18-byte ASCII domain separation prefix. Since newOrder_hash has a fixed length of 32 bytes, the concatenation is unambiguous. The domain separation prefix is mandatory: the private key corresponding to popKey is likely to be used later in other protocols (e.g., TLS handshake signatures), and the nonce is an arbitrary byte string chosen by the server; without domain separation, a malicious server could induce the client to sign a message that is meaningful in another protocol context. The prefix isolates this signature context from all other uses of the same key pair.

5) Compute the signature:

proof = base64url( Sign(privateKey, to_sign) )

Sign(key, message) denotes a complete signing operation over message (with hashing internal to the algorithm). The caller MUST NOT pre-hash message before invocation. For ML-DSA and SLH-DSA, the pure signing mode MUST be used and the context string ctx MUST be the empty string (domain separation is already provided by the to_sign prefix).

The signature algorithm is determined by the key type declared in the key field's SPKI. For Ed25519, ML-DSA, and SLH-DSA, the algorithm field of the SPKI uses the parameter-set-specific OID directly (the parameters field MUST be absent); implementations MUST use the complete OID for algorithm identification and MUST NOT rely solely on OID prefix matching. For EC keys, the algorithm field is id-ecPublicKey (1.2.840.10045.2.1) and the specific curve is identified by the namedCurve OID in the parameters. For RSA keys, the algorithm field is rsaEncryption (1.2.840.113549.1.1.1); signature verification always uses RSASSA-PSS (PS256) regardless of the algorithm OID in the SPKI. Clients MUST generate signatures using RSASSA-PSS with SHA-256, MGF1 with SHA-256, a salt length of 32 bytes, and a trailer field value of 0xBC. If a client uses PKCS#1 v1.5 padding or any other signature algorithm, the server MUST reject the challenge with error type urn:ietf:params:acme:error:badPoP and SHOULD include a detail field indicating “RSA signature algorithm mismatch – expected RSASSA-PSS”.

Table 1
Key type SPKI algorithm identification Signature algorithm
EC P-256 id-ecPublicKey (1.2.840.10045.2.1), namedCurve = secp256r1 (1.2.840.10045.3.1.7) ECDSA with SHA-256
EC P-384 id-ecPublicKey (1.2.840.10045.2.1), namedCurve = secp384r1 (1.3.132.0.34) ECDSA with SHA-384
Ed25519 1.3.101.112 Ed25519 (PureEdDSA, [RFC8032])
RSA rsaEncryption (1.2.840.113549.1.1.1) RSASSA-PSS with SHA-256
ML-DSA-44 2.16.840.1.101.3.4.3.1 ML-DSA-44 [FIPS-204]
ML-DSA-65 2.16.840.1.101.3.4.3.2 ML-DSA-65 [FIPS-204]
ML-DSA-87 2.16.840.1.101.3.4.3.3 ML-DSA-87 [FIPS-204]
SLH-DSA-SHA2-128s (TBD – see NIST CSOR) SLH-DSA-SHA2-128s [FIPS-205]
SLH-DSA-SHA2-128f (TBD – see NIST CSOR) SLH-DSA-SHA2-128f [FIPS-205]
SLH-DSA-SHA2-192s (TBD – see NIST CSOR) SLH-DSA-SHA2-192s [FIPS-205]
SLH-DSA-SHA2-192f (TBD – see NIST CSOR) SLH-DSA-SHA2-192f [FIPS-205]
SLH-DSA-SHA2-256s (TBD – see NIST CSOR) SLH-DSA-SHA2-256s [FIPS-205]
SLH-DSA-SHA2-256f (TBD – see NIST CSOR) SLH-DSA-SHA2-256f [FIPS-205]

Note: The key type names for SLH-DSA follow the naming convention established in FIPS 205. These names use hyphens and include the hash function family (SHA2), security level (128/192/256), and parameter size variant ("s" for small, "f" for fast). This differs from the ML-DSA naming convention but reflects the nomenclature standardized by NIST.

The client MUST use the signature algorithm corresponding to the declared public key type.

The modulus length of an RSA key SHOULD be at least 2048 bits; the server MAY reject RSA keys with modulus length less than 2048 bits and return the urn:ietf:params:acme:error:badPublicKey error. CA policy MAY require a minimum length above this baseline (e.g., 3072 bits); in that case the required minimum SHOULD be stated in the detail field of the badPublicKey error (the examples in Section 3.2 and Section 9.1.5 illustrate such a policy).

Byte encoding of signature values:

  • ECDSA: MUST use the IEEE P1363 compact format (r || s, fixed length equal to twice the byte length of the curve order), per [RFC7518] Section 3.4; ASN.1 DER encoding MUST NOT be used. Note: This encoding is only required for the proof-of-possession signature in the pk-01 challenge. It does not affect the format of signatures that appear in the issued X.509 certificate (which remain ASN.1 DER encoded).

  • RSASSA-PSS: MUST use the PS256 algorithm as defined in [RFC7518] Section 3.5. This specifies RSASSA-PSS with SHA-256, MGF1 with SHA-256, a salt length of 32 bytes, and a trailer field value of 0xBC.

  • Ed25519: MUST use the 64-byte signature encoding defined in [RFC8032] Section 5.1.

  • ML-DSA-44 / 65 / 87: MUST use the byte encoding defined in [FIPS-204].

  • SLH-DSA-SHA2-*: MUST use the byte encoding defined in {{FIPS-205 Section 8.2.

5.2. PoP for KEM Keys

In KEM key mode, the "pk-01" challenge object contains the challenge_ciphertext field. The KEM algorithm is uniquely determined by the AlgorithmIdentifier in the key field's SPKI. The AlgorithmIdentifier OID includes the parameter set identifier.

Table 2
Key type Public key Length (bytes) SPKI AlgorithmIdentifier OID Standard
ML-KEM-512 768 2.16.840.1.101.3.4.4.1 ML-KEM-512 [FIPS-203]
ML-KEM-768 1088 2.16.840.1.101.3.4.4.2 ML-KEM-768 [FIPS-203]
ML-KEM-1024 1568 2.16.840.1.101.3.4.4.3 ML-KEM-1024 [FIPS-203]

The server and client perform the following steps:

Server-side (challenge creation):

1) Execute KEM Encapsulate using the public key from the key field, obtaining a shared secret shared_secret and a ciphertext ct.

2) Derive a MAC key:

prk = HKDF-Extract(salt = "", IKM = shared_secret)
mac_key = HKDF-Expand(prk, info = "ACME-pk-01-KEM v1", L = 32)

The empty salt is used because the shared secret output by ML-KEM possesses sufficient entropy; per [RFC5869], an empty salt is equivalent to the default all-zero salt, consistent with the provisions for the default salt in two-step (extract-then-expand) key derivation in [NIST-SP-800-56C]. See [RFC5869] for HKDF.

3) Store mac_key in the order record (associated with this challenge). shared_secret, prk, and all intermediate states from the Encapsulate process MUST be destroyed after mac_key is derived.

4) The server MUST verify that the length of the ciphertext ct produced by Encapsulate matches the expected ciphertext length for the declared KEM algorithm (as listed in the table above). A length mismatch indicates an implementation or library error, and the server MUST abort challenge creation.

5) Fill the challenge_ciphertext field with the Base64URL encoding of ct.

Client-side (proof generation):

1) Let ct be the raw bytes obtained by Base64URL-decoding the challenge_ciphertext field.

2) Perform KEM Decapsulate(ct) using the private key corresponding to the public key in the key field, obtaining shared_secret.

3) The client MUST verify that the KEM Decapsulate operation succeeds and that the resulting shared_secret is not all-zero nor any other pre‑defined error value (as specified by the KEM algorithm). If decapsulation fails or the shared secret is invalid, the client MUST abort the challenge and MUST NOT submit a proof. The client SHOULD report the error to the user or operator.

4) Derive mac_key using the same parameters as the server:

prk = HKDF-Extract(salt = "", IKM = shared_secret)
mac_key = HKDF-Expand(prk, info = "ACME-pk-01-KEM v1", L = 32)

5) Compute newOrder_hash = SHA-256(raw_newOrder).

6) Compute the proof:

proof = base64url( HMAC-SHA-256(mac_key, newOrder_hash) )

The applicant MUST NOT use shared_secret directly as the HMAC key; mac_key MUST be derived via HKDF. After submitting the proof, the client SHOULD immediately destroy shared_secret, prk, and mac_key from memory (e.g., by overwriting with zeros) to reduce the risk of key material exposure, especially in multi‑tenant environments. The HMAC serves as an implicit key confirmation: if the client does not possess the correct KEM private key, the derived mac_key will differ from the server's, and the HMAC verification will fail. This provides assurance to the server that the client successfully completed the KEM decapsulation and holds the corresponding private key.

If the challenge object contains a kdf_version field, the client and server MUST use the KDF parameters corresponding to that version. Version 1 is defined in this document. Future versions will be defined in separate specifications.

5.3. Client Response Submission

After constructing the proof, the client submits it to the challenge url via an authenticated ACME POST:

POST /acme/chall/abc123 HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json
{
  "proof": "<base64url-encoded proof>"
}

The proof field carries the signature (signature key mode) or HMAC (KEM key mode) as computed above.

5.4. Server Validation

Upon receiving the response, the server:

  1. Retrieves the previously stored newOrder_hash and challenge-specific material (popNonce_bytes for signature mode, mac_key for KEM mode).

  2. Selects the validation path based on the field present in the challenge object:

    • Signature key mode: Constructs to_sign = "ACME-pk-01-sig v1:" ‖ popNonce_bytes ‖ newOrder_hash (see Section 5.1), and verifies the signature using the public key from the key field.

    • KEM key mode: Computes HMAC-SHA-256(mac_key, newOrder_hash) and compares it (using constant-time comparison) with the submitted proof.

  3. If validation succeeds, the challenge state is set to valid; if it fails, to invalid with error urn:ietf:params:acme:error:badPoP.

  4. Once the challenge reaches a terminal state, the server MUST immediately destroy the locally stored popNonce (signature key mode) or mac_key (KEM key mode). Any subsequent request carrying the same proof or referencing a consumed popNonce MUST be rejected.

If a "pk-01" challenge fails validation, it MUST be immediately transitioned to invalid. Clients MUST NOT retry the same challenge URL. Unlike identifier-control challenges such as dns-01, where transient failures (e.g., DNS propagation delays) are common and retries are appropriate, a "pk-01" failure indicates a cryptographic mismatch between the declared public key and the proving private key. This is not a transient condition; retrying the same challenge with the same key would not succeed. To attempt PoP again, a new order MUST be created.

5.5. Order Binding

Both to_sign (signature key mode) and newOrder_hash (KEM key mode, used as HMAC input) include SHA-256(raw_newOrder). This binds the proof to the entire byte sequence of the "newOrder" request, including the identifiers array, the popKey field, and any other fields. Any modification to raw_newOrder will cause PoP verification to fail. This ensures that the public key is cryptographically bound to the specific set of identifiers in the order.

Note: This specification binds the proof to the raw JWS payload bytes of the "newOrder" request to avoid JSON serialization ambiguities. Implementations MUST follow the guidance in Section 9.1.1 to capture these bytes correctly. Future revisions of this specification may consider alternative binding mechanisms (e.g., a canonicalized representation of the order's semantic content) if deployment experience reveals interoperability challenges with the current approach.

5.6. Design Rationale: Why a Challenge?

During the development of this document, an alternative design path was discussed: making proof-of-possession a standalone mechanism outside the ACME challenge framework (e.g., a separate server-declared PoP endpoint). This document elects to model PoP as an ACME challenge for the following engineering reasons:

  • Reuse of the authorization state machine: ACME already defines a robust lifecycle for challenges (pending -> processing -> valid/invalid) with well-understood error handling, retry semantics, and finalization gating (order only becomes ready when all challenges are valid). By representing PoP as a challenge, we inherit this infrastructure without introducing a parallel state machine.

  • Natural composition with identifier-control challenges: In a typical order, authorizations contain both identity challenges (dns-01) and a "pk-01" challenge. Both must reach valid before the order enters ready. The challenge model makes this composition declarative and transparent.

  • Preserving finalization atomicity: Certificate issuance is a high-cost, non-ephemeral operation. Placing PoP inside a challenge guarantees that the order only reaches ready when both identifier control and private key possession have been confirmed, preserving the deterministic semantics of finalization that are central to ACME's reliability.

  • Minimal changes to the ACME ecosystem: Introducing a new, out-of-band PoP mechanism would require changes to ACME client and server state management beyond what is already provided. The challenge approach minimizes the delta.

A comparison with OAuth 2.0 DPoP [RFC9449] is instructive. DPoP attaches a PoP proof to every protected HTTP request, which is appropriate for a resource-access protocol where requests are short-lived and failures are cheap. In contrast, ACME certificate orders are long-lived, multi-step transactions culminating in a cryptographic credential with significant lifetime and security impact. Moving PoP validation to the finalization step (as DPoP would suggest by analogy) would expose clients to costly order failures after all other challenges have been completed. Placing PoP inside a challenge, as this document does, ensures that the order only reaches "ready" when both conditions are met, avoiding late failures.

Note: This design choice does not preclude future work from defining additional, non-challenge PoP mechanisms if the need arises. The "pk-01" challenge demonstrates that the challenge abstraction is sufficiently general to support cryptographic proof-of-possession while maintaining full backward compatibility with [RFC8555].

5.7. KEM PoP Key Derivation Versioning

The HKDF info string "ACME-pk-01-KEM v1" includes a version indicator ("v1") to accommodate potential future changes to the key derivation parameters (e.g., different HKDF hash functions, alternative salt values, or distinct MAC algorithms). If it determines that the KDF parameters need to be updated in the future, the following options are available, and the appropriate choice will be made based on the nature of the change:

  • For incompatible changes to the KDF parameters, a new challenge type (e.g., "pk-02") would be defined with updated parameters. This approach is appropriate when the change would cause a server and client using different parameters to derive different MAC keys, leading to verification failures.

  • For backwards-compatible additions, additional algorithms could be registered alongside the existing ones in the IANA registry (see Appendix A.3) without changing the KDF parameters.

The version indicator in the info string serves primarily as a self-documenting feature, making key derivation logs and debugging output unambiguous about which parameter set is in use. Implementers MUST use the info string exactly as specified ("ACME-pk-01-KEM v1") and MUST NOT substitute a different version unless a future specification defines a new challenge type.

6. Finalization

6.1. Order Readiness with pk-01

An order that contains one or more "pk-01" challenges across its authorizations transitions to ready only when all those challenges are valid (and all other required challenges are also valid). The server MUST ensure that all "pk-01" challenges in the order carry the same key (which matches the popKey); if a mismatch is detected at any point, the order MUST be considered invalid.

As specified in Section 4.3, if any "pk-01" challenge in any authorization transitions to invalid, the entire order MUST be immediately transitioned to invalid.

6.2. Finalize Request

If the order has any "pk-01" challenges that were successfully validated, the client MUST send an empty finalize request:

POST /acme/order/xyz/finalize HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json

{}

The empty object {} is a valid JSON payload. Server implementations MUST accept an empty JSON object as the finalize request body when the order contains pk-01 challenges. Note: the JWS payload MUST be exactly {}. An empty-string payload carries POST-as-GET semantics in ACME ([RFC8555] Section 6.3), and the server MUST NOT interpret a POST-as-GET request sent to the finalize URL as a finalization request.

The server MUST reject any finalize request that contains a csr field when the order includes "pk-01" challenges, returning a urn:ietf:params:acme:error:malformed error. The server MUST NOT attempt to extract a public key from the CSR or compare it with the popKey; the presence of a CSR in a "pk-01" order is a protocol error.

If the order does not contain any "pk-01" challenge, the standard [RFC8555] finalization flow applies, and the client MUST submit a PKCS#10 CSR.

6.3. Certificate Issuance

When issuing the certificate, the server uses:

  • Public key: The SPKI from the validated popKey / key field.

  • Identifiers: The authorized identifiers from the order (e.g., dns names) populate the SAN extension. Subject DN may be determined by CA policy or a profile extension.

Before writing the public key into the certificate, the server MUST confirm that the SPKI is byte-for-byte identical to the SPKI from the popKey field. The server MUST NOT perform any DER normalization or re-encoding.

The signature algorithm used by the CA when signing the issued certificate (e.g., sha256WithRSAEncryption, RSASSA-PSS, or ecdsa-with-SHA256) is determined by the CA's policy and is independent of the proof-of-possession signature algorithm used in the pk-01 challenge. CAs MAY continue to use their existing certificate signature algorithms; the pk-01 challenge does not impose any constraint on the certificate's own signature algorithm.

7. Security Considerations

7.1. Security Model and Threat Analysis

The "pk-01" challenge provides a cryptographic proof that, at the time the challenge completes, the requesting entity possesses the private key corresponding to the public key declared in the popKey field. This proof does not imply any form of identifier control; identifier authorization remains the sole responsibility of existing ACME challenge types (dns-01, http-01, tls-alpn-01, email-reply-00, etc.).

Security value of PoP across deployment scenarios. The value of PoP varies significantly depending on the deployment context:

  • Standard Web PKI (dns-01/http-01): An attacker who can pass domain control challenges can generate their own key pair. PoP here prevents accidental misconfiguration (e.g., submitting a malformed public key) but does not materially increase security against an active adversary. The primary security control in Web PKI is identifier control validation, not PoP.

  • Device attestation: When combined with hardware attestation, PoP provides significant additional security. It ensures that the key whose possession is proved is the same key that the attested device controls. Without PoP, a device could pass attestation checks but then use a different key for the certificate, breaking the binding between device identity and the certified public key.

  • Escrowed encryption keys: When a KMC holds encryption keys on behalf of clients, PoP proves that the KMC actually possesses the escrowed key it claims to hold. This prevents a KMC from requesting certificates for keys it does not control.

  • Proxy Certificate Management: When a network management platform requests certificates as a proxy, PoP serves as a critical security anchor. It mandates that the device (the private key holder) must be online and participate in the certificate issuance process. Even if the proxy controls order creation, it cannot bypass PoP to obtain certificates for keys outside the device's control. In proxy scenarios, PoP delivers security benefits comparable to device attestation, as it distinguishes between a proxy merely claiming to act on behalf of a device and genuine consent from the device itself. When combined with device-attest-01, a complete trust chain can be established from the device's hardware identity to the public key in the certificate.

  • KEM keys: For KEM keys, PoP is not merely a security enhancement; it is the only available mechanism to prove key possession, since KEM keys cannot sign.

The overall security of a certificate issuance that includes "pk-01" rests on the joint satisfaction of two independent properties:

  1. Identifier control: One or more identifier-specific challenges prove that the requester controls the identifiers to be included in the certificate's SAN (or other identity fields).

  2. Private key possession: The "pk-01" challenge proves that the requester holds the private key corresponding to the public key that will be bound into the certificate.

When both conditions are met, the issued certificate cryptographically binds a controlled identifier to a controlled public key. Neither challenge type alone is sufficient for secure issuance.

Threats outside the scope of "pk-01":

  • A malicious actor who legitimately controls a domain name but submits a "newOrder" with a popKey containing a third party's public key will succeed in the identifier-control challenges but will be unable to complete the "pk-01" challenge (because they do not possess the corresponding private key). The order will not become ready.

  • A malicious actor who legitimately possesses a private key but does not control any authorized identifier will succeed in "pk-01" but will fail the identifier-control challenges. Again, the order will not become ready.

  • "pk-01" does not defend against certificate requests originating from entities that have legitimately obtained control of both the authorized identifier and the certificate private key through out-of-band compromise. Such scenarios must be addressed through account security, revocation infrastructure, and operational practices.

Warning on partial proof-of-possession for multi‑identifier certificates:
When an order contains multiple identifiers and the CA's policy requires proof-of-possession (pk-01) only for a subset of those identifiers (e.g., only for device identifiers but not for DNS names), the overall security of the resulting certificate is limited by the weakest identifier validation. An attacker who can compromise the validation of an identifier that does not require PoP could potentially obtain a certificate that binds a controlled identifier to a public key without proving possession of the corresponding private key. CAs SHOULD either require PoP for all identifiers in a certificate or clearly document the risks of partial PoP in their Certificate Policy (CP) and Certificate Practice Statement (CPS).

7.2. Cryptographic Binding

The cryptographic binding between the certificate public key and the authorized identifiers is jointly established by the "pk-01" challenge and the byte-level public key consistency check at finalization: the PoP input includes SHA-256(raw_newOrder), binding the signature or MAC to the entire byte sequence of the "newOrder" request (including the identifiers array, the popKey field, and any other extension fields); when issuing the certificate, the server further requires the certificate public key to be byte-identical to the SPKI from the popKey field (see Section 6.3). Together, these constitute an end-to-end binding between the authorized identifiers and the public key of the issued certificate.

7.3. Nonce and KEM Key Management

The popNonce field MUST have at least 128 bits of entropy [RFC4086] and MUST NOT contain characters outside the Base64URL alphabet (including the padding character =). The popNonce MUST be generated using the CSPRNG as specified in [RFC4086], preferably one compliant with NIST SP 800-90A. The same nonce MUST NOT be used for multiple challenges; once the challenge enters a terminal state, the server MUST immediately mark the nonce as consumed, and any subsequent request carrying the same popNonce MUST be rejected.

To manage memory in high‑volume deployments, servers MAY implement nonce tracking using a time‑based sliding window (e.g., remember consumed nonces for a limited period, such as twice the maximum expected challenge lifetime, after which the nonce can be forgotten). Servers SHOULD ensure that the window is long enough to cover all legitimate retries and finalisation attempts.

The popNonce value is transmitted over HTTPS and is protected in transit by TLS. However, if the popNonce is exposed through server logs, debugging output, or error messages, an attacker who obtains the popNonce before the legitimate client submits its proof could potentially pre-compute a valid signature. Servers SHOULD NOT log the raw nonce value; instead, they SHOULD log a cryptographic hash of the nonce (e.g., SHA-256(popNonce_bytes)).

In KEM key mode, mac_key MUST be derived via HKDF [RFC5869] from shared_secret obtained through KEM Decapsulate; using shared_secret directly as the HMAC key does not satisfy the key derivation requirements of [NIST-SP-800-56C]. The HKDF info string "ACME-pk-01-KEM v1" isolates the derived key from any keys that might be derived from the same KEM public key in other protocols (such as TLS, JOSE, etc.). An empty salt is used in the HKDF-Extract step because the shared secret from ML-KEM possesses sufficient entropy; per [RFC5869], an empty salt is equivalent to the default all-zero salt, and this choice is consistent with the provisions for the default salt in two-step key derivation in [NIST-SP-800-56C].

When comparing the client-submitted proof with the locally computed HMAC output, the server MUST use constant-time comparison to avoid leaking byte-level information through timing side channels. This requirement is normative because timing leaks in MAC verification can enable brute-force attacks against the MAC key.

Servers SHOULD implement rate limiting on "pk-01" challenge creation and proof submission, limiting the number of challenges per account and per IP address over time. For KEM key mode, where the Encapsulate operation is computationally expensive, rate limiting and concurrency limits (see Section 9.1.4) are particularly important.

7.4. Algorithm and Key Rejection

The server SHOULD reject key types and signature/KEM algorithms that do not meet current security baselines (see Section 5.1 and Section 5.2). The server SHOULD declare the supported key types and algorithm sets in the Directory metadata.

7.5. Revocation of KEM-Bound Certificates

Since KEM keys do not cryptographically support signature operations, revocation (per [RFC8555] Section 7.6) of a certificate bound to a KEM public key can only be initiated by the ACME account key; the path of "signing the revocation request with the certificate private key" is not applicable to such certificates.

This creates a structural dependency: the security of KEM certificate revocation relies entirely on the security of the ACME account key. For signature certificates, there is a second factor — the certificate private key can independently authorize revocation. For KEM certificates, this second factor does not exist.

This dependency has a circular aspect when combined with short-lived certificates. Short-lived certificates are often recommended as a mitigation for revocation limitations. However, automated renewal of short-lived certificates itself depends on the ACME account key. If the account key is compromised, the attacker can both prevent legitimate renewal and request replacement certificates.

Operational mitigations include:

  • Protecting ACME account keys in hardware security modules (HSMs) or secure enclaves.

  • Requiring multi-factor authentication for account key operations.

  • Implementing out-of-band revocation confirmation channels (e.g., confirming revocation requests through a separate administrative interface).

  • Issuing KEM-bound certificates with validity periods that balance the risk of revocation failure against the overhead of frequent renewal.

These mitigations are operational rather than protocol-level. This is appropriate: the limitation is cryptographic, not a protocol deficiency, and cannot be fully resolved at the ACME layer.

Relying party awareness: Protocols that validate certificate revocation status should be aware that some certificates may not support private-key-based revocation, and should not treat the absence of this capability as an error. Certificate transparency and OCSP stapling remain fully functional for KEM certificates. KEM certificates are structurally identical to traditional X.509 certificates and require no modifications to CT logs or OCSP responders. However, CT log servers SHOULD accept certificates carrying the KEM AlgorithmIdentifier OIDs (listed in Section 8.5) even if they do not perform specialised validation of those key types; rejecting such certificates would break transparency for a valid class of certificates.

Key Usage for KEM certificates:

X.509 certificates containing a KEM public key (e.g., ML-KEM) do not fit neatly into existing Key Usage bits defined for signature or encryption. CAs issuing such certificates SHOULD set the keyEncipherment bit (consistent with the key’s purpose in key exchange). If future PKIX standards define a dedicated keyAgreement or keyEncapsulation bit, CAs MAY adopt those. In the absence of such bits, the CA SHOULD include a key usage extension that reflects the intended use as permitted by local policy. The absence of a perfect match does not invalidate the certificate; relying parties SHOULD accept KEM certificates for key encapsulation purposes when the key usage extension allows keyEncipherment.

Application support for KEM certificates:
The use of KEM public keys in application protocols such as TLS or S/MIME is not yet fully standardized. Relying parties MUST ensure that their TLS, S/MIME, or other relevant implementations can correctly parse and handle X.509 certificates containing KEM AlgorithmIdentifier OIDs (see Section 8.5). Deployers should be aware that KEM certificates may not be usable in all existing systems until broader protocol support is available. This document provides the necessary infrastructure for issuing such certificates; it does not mandate their immediate applicability.

7.6. Algorithm Identifier Stability for Post-Quantum Algorithms

This document references AlgorithmIdentifier OIDs defined in FIPS 203 [FIPS-203], FIPS 204 [FIPS-204], and FIPS 205 [FIPS-205]. While these OIDs are stable as of the publication of those standards, implementers should be aware that algorithm identifiers occasionally change during the standardization process or when algorithms are revised. If a future update to these standards changes the OIDs, implementations MUST ensure that the OIDs used in the popKey/key fields, in the "pk-01" challenge processing, and in the issued certificate are consistent. An OID mismatch will cause PoP verification to fail or the certificate chain to be invalid.

If NIST publishes errata or updates to FIPS 203, FIPS 204, or FIPS 205, the IANA registry established in Section 8.5 will be updated accordingly. Implementers SHOULD follow the latest published version of these standards. During transition periods, servers SHOULD support both old and new OIDs, and advertise their support in the Directory metadata.

For algorithms whose OIDs are marked as TBD (e.g., SLH-DSA parameter sets in Section 8.5), the following transition procedure applies when NIST finalises the OIDs:

  • A six‑month dual support window begins upon publication of the definitive OIDs. During this period, servers SHOULD accept both the old (draft) OID (if any) and the new official OID.

  • Clients SHOULD use the new OID after the window expires.

  • The IANA registry will be updated to reflect the final OIDs.

  • Implementers SHOULD monitor the NIST CSOR and IANA registry for changes.

7.7. Relationship to Established PoP Security

The security properties of the PoP mechanism defined here align with those established for PoP tokens [RFC8747] and DPoP [RFC9449]. Readers should consult the Security Considerations sections of those documents for a broader discussion of threats such as key exfiltration, replay of proofs, and the importance of context binding. In particular, the use of order-specific nonces and the inclusion of SHA-256(raw_newOrder) in the proof input provide freshness and anti-replay guarantees within the ACME transaction, analogous to the DPoP nonce and the binding to the HTTP request URI.

7.8. Privacy Considerations

The popKey field carries the public key to be certified, which is intended to be included in a publicly-visible certificate. However, the reuse of the same popKey across multiple orders can serve as a correlation identifier, linking otherwise unrelated certificate requests to the same entity. This risk is most pronounced when orders use different domain names or identity attributes.

There is a trade-off between privacy and computational efficiency:

  • Fresh key per order (privacy-preserving): Prevents cross-order correlation via popKey. Recommended for general deployments, particularly those using standard Web PKI certificates. The additional key generation overhead is typically negligible compared to the overall ACME transaction.

  • Reused key across orders (efficient): Reduces key generation overhead but creates a long-term identifier. May be necessary for hardware-bound keys where key generation is expensive or where the key is pre-provisioned (e.g., TPM-bound keys, escrowed encryption keys). Deployers using this strategy should be aware of the privacy implications.

To mitigate this risk:

  • Clients SHOULD generate a fresh key pair for each order, as recommended in Section 9.2. This prevents cross-order correlation via the popKey.

  • Servers SHOULD NOT retain popKey values beyond the lifetime of the order's authorization, except as required for certificate issuance or audit logging.

  • If a client must reuse a key pair (e.g., for hardware-bound keys in IoT devices), it should be aware that the key may serve as a long-term identifier for that device.

8. IANA Considerations

8.1. ACME Directory Metadata Fields Registry

popSupported appears inside the "meta" object. IANA is requested to add the following entry to the "ACME Directory Metadata Fields" registry (established by [RFC8555]). The Change Controller is the IETF.

Table 3
Field Name Field Type Reference
popSupported boolean this document

The popSupported field, when present, MUST be placed inside the "meta" object of the directory response. It indicates that the server supports the "pk-01" challenge as defined in this document.

8.2. ACME Validation Methods Registry

IANA is requested to add the following entry to the "ACME Validation Methods" registry. The Change Controller is the IETF.

Table 4
Label Identifier Type ACME Reference
pk-01 (any) Y this document

"pk-01" is a PoP challenge and is not bound to a specific identifier type (the standard columns of the "ACME Validation Methods" registry do not include a notes column; this clarification is provided in the body text).

8.3. ACME Order Object Fields Registry

IANA is requested to add the following entries to the "ACME Order Object Fields" registry established by [RFC8555]. The Change Controller is the IETF.

Table 5
Field Name Field Type Configurable Reference
popKey string true this document
popKeyAccepted boolean false this document

popKey is set by the client in the "newOrder" request (configurable); popKeyAccepted is set only by the server in the order object, and a value of true indicates that the server has accepted the popKey and will use pk-01 (absence of the field indicates that the server did not process popKey; see Section 3.3).

The fields within the "pk-01" challenge object (key, nonce, challenge_ciphertext) and the challenge response field (proof) are defined by the challenge type itself (see Section 4.2 and Section 5.3). Following [RFC8555] convention, challenge object fields have no separate IANA registry, and no additional IANA action is required.

8.4. ACME Error Types Registry

IANA is requested to add the following entries to the "ACME Error Types" registry. The Change Controller is the IETF.

Table 6
Type Description Reference
badPoP The proof-of-possession verification has failed this document
popNotSupported The server does not support the pk-01 challenge this document
popKeyRejectedByPolicy The server supports pk-01 but refused to accept the popKey due to local policy (e.g., account not authorised for CSR‑less issuance). this document

(The "ACME Error Types" registry does not include an HTTP status code column; both errors are typically returned with HTTP 400, as shown in the examples in Section 9.1.5.)

8.5. ACME PoP Key Algorithm Registry

IANA is requested to establish a new registry named "ACME PoP Key Algorithms" to facilitate future updates to the set of supported signature and KEM algorithms without requiring a new RFC. The Change Controller is the IETF.

Initial contents:

Signature Algorithms:

Table 7
Algorithm Name Key Type SPKI Algorithm Identification Reference
ECDSA-SHA-256 EC P-256 id-ecPublicKey (1.2.840.10045.2.1) + secp256r1 (1.2.840.10045.3.1.7) this document, [RFC5480]
ECDSA-SHA-384 EC P-384 id-ecPublicKey (1.2.840.10045.2.1) + secp384r1 (1.3.132.0.34) this document, [RFC5480]
Ed25519 Ed25519 1.3.101.112 this document, [RFC8032]
RSASSA-PSS RSA rsaEncryption (1.2.840.113549.1.1.1) this document, [RFC7518]
ML-DSA-44 ML-DSA-44 2.16.840.1.101.3.4.3.17 this document, [FIPS-204]
ML-DSA-65 ML-DSA-65 2.16.840.1.101.3.4.3.18 this document, [FIPS-204]
ML-DSA-87 ML-DSA-87 2.16.840.1.101.3.4.3.19 this document, [FIPS-204]
SLH-DSA-SHA2-128s SLH-DSA-SHA2-128s 2.16.840.1.101.3.4.3.20 this document, [FIPS-205]
SLH-DSA-SHA2-128f SLH-DSA-SHA2-128f 2.16.840.1.101.3.4.3.21 this document, [FIPS-205]
SLH-DSA-SHA2-192s SLH-DSA-SHA2-192s 2.16.840.1.101.3.4.3.22 this document, [FIPS-205]
SLH-DSA-SHA2-192f SLH-DSA-SHA2-192f 2.16.840.1.101.3.4.3.23 this document, [FIPS-205]
SLH-DSA-SHA2-256s SLH-DSA-SHA2-256s 2.16.840.1.101.3.4.3.24 this document, [FIPS-205]
SLH-DSA-SHA2-256f SLH-DSA-SHA2-256f 2.16.840.1.101.3.4.3.25 this document, [FIPS-205]

Note: The OIDs for ML-DSA and SLH-DSA are assigned under the sigAlgs arc of the NIST CSOR (Computer Security Objects Register); the ML-KEM OIDs are assigned under the kems arc. Implementers should verify against the latest NIST CSOR publication.

KEM Algorithms:

Table 8
Algorithm Name Key Type Public key Length (bytes) OID Reference
ML-KEM-512 ML-KEM-512 768 2.16.840.1.101.3.4.4.1 this document, [FIPS-203]
ML-KEM-768 ML-KEM-768 1088 2.16.840.1.101.3.4.4.2 this document, [FIPS-203]
ML-KEM-1024 ML-KEM-1024 1568 2.16.840.1.101.3.4.4.3 this document, [FIPS-203]

New entries to this registry are assigned on a Specification Required basis per [RFC8126]. The designated expert should verify that the proposed algorithm has a publicly available specification and that the OID is correctly registered.

9. Implementation Considerations

9.1. ACME Server (CA)

9.1.1. Obtaining newOrder_hash

The input raw_newOrder to newOrder_hash is the raw byte sequence of the "newOrder" request's JWS protected payload after BASE64URL-DECODE and before JSON parsing.

The server MUST NOT serialize the parsed JSON object back to bytes for use as raw_newOrder: JSON normalization (field ordering, whitespace handling, Unicode escape forms, number representations, etc.) would alter the byte representation, causing the server's computed hash to differ from the client's.

The following implementation pattern is RECOMMENDED to avoid serialization ambiguities and ensure consistency:

  1. When receiving a "newOrder" request, the server first extracts and base64url-decodes the JWS protected payload, producing raw_newOrder.

  2. The server MUST compute and store newOrder_hash = SHA-256(raw_newOrder) immediately after JWS signature verification succeeds, before parsing the JSON body. If the order creation subsequently fails (e.g., due to an invalid identifier), the server SHOULD discard the stored newOrder_hash as part of the transaction rollback.

  3. The server MAY also persist raw_newOrder for auditing purposes, but newOrder_hash is sufficient for "pk-01" challenge validation.

  4. The server MUST NOT use any other representation of the newOrder payload (e.g., a re-serialized JSON object) when computing the hash for PoP validation.

By computing the hash at the point of signature verification, the server guarantees that the same byte sequence that was authenticated by the client's account key is used for the "pk-01" proof binding.

For performance optimization in high-volume deployments, the server SHOULD maintain a secondary index on the newOrder_hash value in the order database. Note that newOrder_hash is not guaranteed to be unique — two byte-identical newOrder payloads (e.g., a retry carrying the same identifiers and popKey) produce the same hash — so it MUST NOT be used as a primary key; the authoritative lookup key is the order ID, and the newOrder_hash index serves only to accelerate lookup during the challenge validation phase.

While the method described above (retaining the exact bytes of the JWS payload) is the primary requirement, implementers seeking additional interoperability across different JSON libraries MAY also compute a canonical representation of the order object using JSON Canonicalization Scheme (JCS) [RFC8785] for debug or fallback purposes. However, the only authoritative binding is based on the raw bytes as transmitted; clients and servers MUST NOT re‑serialize the JSON object from parsed data for the purpose of computing newOrder_hash. Implementers are encouraged to test their JSON serialisation with a fixed test vector to ensure that field ordering and whitespace are stable.

9.1.2. Storing and Validating popKey

Upon receiving popKey in a newOrder request, the server MUST:

  • Decode and validate the SPKI per Section 3.2. Implementations SHOULD use ASN.1 parsing libraries that have been security-audited and fuzz-tested, and SHOULD enforce a maximum length on the popKey field (e.g., 4096 bytes — sufficient for the largest SPKI among the algorithms in this document, ML-DSA-87, whose Base64URL encoding is roughly 3.5KB) to mitigate malformed input attacks. ACME servers SHOULD accept a maximum newOrder payload size of 64KB to leave headroom for future larger-key algorithms registered per Section 8.5. Servers MAY advertise this limit in the directory object.

  • Store the exact bytes received as the authoritative public key for the order.

  • Ensure that all "pk-01" challenges created for the order use the byte-identical SPKI in their key field.

9.1.3. Signature Key Mode

  • The server MUST generate a unique nonce for each "pk-01" challenge and immediately mark it as consumed once the challenge reaches a terminal state.

  • The byte length of nonce SHOULD be between 16 and 32 bytes.

  • The server MUST perform SPKI format validation on the key field and store it as the originally received bytes (see Section 9.1.2 and Section 6.3).

9.1.4. KEM Key Mode

  • After the KEM Encapsulate operation completes, the server MUST:

    • Immediately derive mac_key per Section 5.2;

    • Store mac_key in the order record. Implementations SHOULD protect mac_key in memory using secure key storage mechanisms (e.g., locked memory pages, hardware security modules, or secure enclaves) where available, especially in multi-tenant CA environments;

    • Immediately destroy shared_secret, HKDF intermediate states, and all temporary materials.

  • mac_key MUST be immediately destroyed once the challenge reaches a terminal state.

  • When comparing the client-submitted proof with the locally computed HMAC output, the server MUST use constant-time comparison to avoid timing side channels.

  • Servers SHOULD implement rate limiting specifically for KEM Encapsulate operations, as they are computationally more expensive than signature verification.

  • In addition to rate limiting, servers SHOULD implement a maximum concurrency limit for KEM Encapsulate operations. When the concurrency limit is reached, the server MAY queue additional requests or return a 503 (Service Unavailable) response with a Retry-After header. The concurrency limit SHOULD be set based on the available CPU resources and the expected latency of KEM Encapsulate operations.

9.1.5. Error Returns

pk-01-related errors SHOULD use the [RFC9457] Problem Details format:

{
  "type": "urn:ietf:params:acme:error:badPoP",
  "detail": "Proof-of-possession verification failed",
  "status": 400
}

When returning a badPublicKey error due to algorithm or key parameter incompatibility, the server SHOULD include specific details in the detail field, for example:

{
  "type": "urn:ietf:params:acme:error:badPublicKey",
  "detail": "RSA key length 2048 is below the required minimum of 3072",
  "status": 400
}

9.1.6. Audit Logging

To support compliance and operational requirements, CAs SHOULD record the following information for each "pk-01" challenge:

  • Order ID and authorization ID.

  • The SPKI of the popKey (or a cryptographic hash thereof).

  • The algorithm type and parameters.

  • A hash of the popNonce (for signature key mode) or the challenge_ciphertext (for KEM key mode).

  • The newOrder_hash value used for PoP binding.

  • Timestamp of client proof submission.

  • Verification result (success or failure, and error type if applicable).

  • Identifier of the CA key used for certificate issuance.

This information enables post-issuance audit of the PoP verification process and facilitates troubleshooting of failed challenges. CAs should ensure that these audit logs satisfy applicable compliance frameworks, including CAB/F Baseline Requirements for certificate request logging and ETSI TS 119 403 event log requirements. The audit recommendations in this document are compatible with these frameworks but do not replace their specific requirements.

9.2. ACME Client

  • The client MUST ensure that the private key used for the signature or KEM operation strictly corresponds to the public key declared in the popKey field.

  • The client MUST retain the exact byte sequence of the newOrder request's JWS payload locally, and use the same byte sequence to compute newOrder_hash during the "pk-01" challenge phase. The client MUST NOT serialize a parsed JSON object back to bytes for use as raw_newOrder. In practice, this means the client should capture the raw JSON payload bytes before constructing the JWS and sending the HTTP request. For example:

    • In Python: construct the JSON payload as a string literal or manually concatenated bytes (e.g., b'{"identifiers":[{"type":"dns","value":"example.com"}],"popKey":"..."}'). Retain this exact byte sequence for later hash computation, then construct the JWS and send the request. Do not use json.dumps() on a dictionary, as it may produce different byte representations (e.g., field ordering, whitespace) that would change newOrder_hash. If a dictionary must be used, ensure that the serialization is fully deterministic and matches the bytes that will be transmitted; the safest approach is to keep the raw bytes from the start.

    • In Go: json.Marshal the payload to a []byte, retain this slice, then use it for both JWS construction and later hash computation.

    • In Java: serialize the payload using a JSON library that produces deterministic output, retain the byte array, then construct the JWS and send the request. Implementation note: The client MUST use the exact byte sequence that will be sent as the JWS payload. Constructing the payload from a dictionary and then serializing it (e.g., with json.dumps) can lead to nondeterministic field ordering or whitespace, causing the computed newOrder_hash to differ from the bytes actually transmitted. The recommended practice is to construct the JSON payload as a raw byte string or to use a deterministic serialization that is guaranteed to match the wire format. The examples below illustrate this principle.

  • The key principle is to retain the exact bytes that were used as the JWS payload, before Base64URL encoding.

  • As an optimization, the client MAY compute newOrder_hash immediately after sending the "newOrder" request, and then discard the raw bytes, retaining only the 32-byte hash value.

  • The client SHOULD generate a fresh key pair for each order. Reuse of the same popKey across multiple orders is NOT RECOMMENDED as it may weaken the binding between a specific certificate and its intended context, and could complicate revocation if the private key is later compromised.

  • The client SHOULD check the popSupported field in the Directory metadata before including popKey in a newOrder request. If popSupported is absent or false, the client SHOULD fall back to the standard CSR-based flow without sending popKey.

  • The client MUST select the PoP construction method based on the field present in the "pk-01" challenge object (nonce or challenge_ciphertext).

  • When the order does not contain any "pk-01" challenge (or the order object lacks popKeyAccepted: true), the finalize stage MUST submit a PKCS#10 CSR as defined in [RFC8555].

  • The client SHOULD use a key pair dedicated to the certificate, distinct from the ACME account key.

For clients using HSMs or PKCS#11 tokens, the popKey field's SPKI can be exported from the hardware module's key handle. The PoP proof should be computed using the hardware module's signature or decryption interfaces rather than exporting the private key to software. ACME client libraries SHOULD provide dedicated API methods to support the "pk-01" flow, such as an order_with_popkey (identifiers, private_key) method that automatically handles SPKI extraction, raw_newOrder retention, and PoP proof computation. Libraries should also automatically detect the server's popSupported metadata and select the appropriate issuance flow.

Handling network retries:
If the client experiences a transient network error while sending the "newOrder" request and chooses to retry the same request (i.e., with the same order content), it SHOULD keep the original raw_newOrder bytes unchanged and reuse the previously computed newOrder_hash. However, the server may have already consumed the original nonce (if any) associated with the previous attempt. To avoid nonce reuse issues, the client SHOULD create a new order (a fresh newOrder request) for each retry, rather than resending the identical JWS payload. Retrying the same order with the same nonce may be rejected by the server as a replay. The client can obtain a fresh nonce by sending a GET /new-nonce request before each retry.

10. Examples

10.1. Signature Key with DNS Identifier

The applicant has DNS control over "example.com" and a P-256 key pair (private key d, public key SPKI bytes <spki_bytes>). The server advertises popSupported: true in its Directory metadata.

Step 1: newOrder request

POST /acme/new-order HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json
{
  "identifiers": [
    { "type": "dns", "value": "example.com" }
  ],
  "popKey": "<base64url(spki_bytes)>"
}

Step 2: Server returns order and authorization with challenges

Order object:

{
  "status": "pending",
  "identifiers": [
    { "type": "dns", "value": "example.com" }
  ],
  "authorizations": [
    "https://acme.example.com/acme/authz/dnsAuthz"
  ],
  "popKey": "<base64url(spki_bytes)>",
  "popKeyAccepted": true,
  "finalize": "https://acme.example.com/acme/finalize/xyz"
}

Authorization for the dns identifier:

{
  "status": "pending",
  "identifier": { "type": "dns", "value": "example.com" },
  "challenges": [
    {
    "type": "dns-01",
    "url": "https://acme.example.com/acme/chall/dns01",
    "status": "pending",
    "token": "some-dns-token"
    },
    {
    "type": "pk-01",
    "url": "https://acme.example.com/acme/chall/pk789",
    "status": "pending",
    "key": "<base64url(spki_bytes)>",
    "popNonce": "Kz3mVpQeRd9fLwYbN5hXuT6oJsIc0vAg2nEp1yMrFqZ"
    }
  ]
}

Step 3: Client completes both challenges

Client fulfills dns-01 as per [RFC8555] Section 8.4. For "pk-01", it computes:

raw_newOrder   = <exact bytes of step 1 newOrder JSON>
newOrder_hash  = SHA-256(raw_newOrder)
popNonce_bytes    = base64url-decode("Kz3mVpQeRd9fLwYbN5hXuT6oJslc0vAg2nEp1yMrFqZ")
to_sign        = "ACME-pk-01-sig v1:" || popNonce_bytes || newOrder_hash
proof          = base64url( ECDSA-Sign(d, to_sign) )    # IEEE P1363 encoding

And POSTs:

POST /acme/chall/pk789 HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json

{ "proof": "<base64url signature>" }

Step 4: Both challenges become valid, order ready, finalize

POST /acme/order/xyz/finalize HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json

{}

The server issues a certificate with example.com in SAN and the SPKI from the popKey as public key.

10.2. KEM Key with Device Attestation

An IoT device with an ML-KEM-768 key pair and a TPM-based device identity enrolls. The server advertises popSupported: true and attaches both device-attest-01 and pk-01 challenges to the device identifier authorization.

Step 1: newOrder request

POST /acme/new-order HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json
{
  "identifiers": [
    { "type": "dns", "value": "device-serial-12345" }
  ],
  "popKey": "<base64url(ml-kem-768-spki)>"
}

Step 2: Server returns order and authorization with challenges

Order object includes popKeyAccepted: true. Authorization contains both device-attest-01 and "pk-01" challenges. The "pk-01" challenge contains challenge_ciphertext.

Step 3: Client performs KEM PoP

ct = base64url-decode(challenge_ciphertext)
shared_secret = ML-KEM-768.Decapsulate(sk, ct)
prk = HKDF-Extract(salt = "", IKM = shared_secret)
mac_key = HKDF-Expand(prk, info = "ACME-pk-01-KEM v1", L = 32)
raw_newOrder = <exact bytes of step 1 newOrder JSON>
newOrder_hash = SHA-256(raw_newOrder)
proof = base64url( HMAC-SHA-256(mac_key, newOrder_hash) )

And POSTs:

POST /acme/chall/pk890 HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json

{ "proof": "<base64url MAC>" }

Step 4: Both challenges valid, finalize

POST /acme/order/xyz/finalize HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json

{}

10.3. Fallback When Server Does Not Support pk-01

A client that requests "pk-01" but whose server does not support it (Directory has no popSupported: true) receives a clear indication to fall back to CSR.

Step 1: Client checks Directory

{
  "newNonce": "https://acme.example.com/acme/new-nonce",
  "newOrder": "https://acme.example.com/acme/new-order"
}

No popSupported field is present, so the client falls back to CSR without attempting popKey.

Alternatively, if the client sends popKey anyway:

Step 1: newOrder request

POST /acme/new-order HTTP/1.1
Host: acme.example.com
Content-Type: application/jose+json
{
  "identifiers": [
    { "type": "dns", "value": "example.com" }
  ],
  "popKey": "<base64url(spki_bytes)>"
}

Step 2: Server rejects the request

{
  "type": "urn:ietf:params:acme:error:popNotSupported",
  "detail": "The server does not support pk-01. Retry without popKey.",
  "status": 400
}

11. References

11.1. Normative References

[FIPS-203]
"Module-Lattice-Based Key-Encapsulation Mechanism (ML-KEM)", .
[FIPS-204]
"Module-Lattice-Based Digital Signature Standard", .
[FIPS-205]
"Stateless Hash-Based Digital Signature Standard", .
[X.690]
"Information technology – ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)", .
[RFC8555]
Barnes, R., Hoffman-Andrews, J., McCarney, D., and J. Kasten, "Automatic Certificate Management Environment (ACME)", RFC 8555, DOI 10.17487/RFC8555, , <https://www.rfc-editor.org/info/rfc8555>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC5480]
Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk, "Elliptic Curve Cryptography Subject Public Key Information", RFC 5480, DOI 10.17487/RFC5480, , <https://www.rfc-editor.org/info/rfc5480>.
[RFC7515]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, , <https://www.rfc-editor.org/info/rfc7515>.
[RFC4086]
Eastlake 3rd, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, DOI 10.17487/RFC4086, , <https://www.rfc-editor.org/info/rfc4086>.
[RFC8032]
Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, , <https://www.rfc-editor.org/info/rfc8032>.
[RFC7518]
Jones, M., "JSON Web Algorithms (JWA)", RFC 7518, DOI 10.17487/RFC7518, , <https://www.rfc-editor.org/info/rfc7518>.
[RFC5869]
Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)", RFC 5869, DOI 10.17487/RFC5869, , <https://www.rfc-editor.org/info/rfc5869>.
[RFC8126]
Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/info/rfc8126>.
[RFC9457]
Nottingham, M., Wilde, E., and S. Dalal, "Problem Details for HTTP APIs", RFC 9457, DOI 10.17487/RFC9457, , <https://www.rfc-editor.org/info/rfc9457>.

11.2. Informative References

[I-D.aaron-acme-profiles]
Gable, A., "Automated Certificate Management Environment (ACME) Profiles Extension", Work in Progress, Internet-Draft, draft-aaron-acme-profiles-01, , <https://datatracker.ietf.org/doc/html/draft-aaron-acme-profiles-01>.
[NIST-SP-800-56C]
"Recommendation for Key-Derivation Methods in Key-Establishment Schemes", .
[RFC2986]
Nystrom, M. and B. Kaliski, "PKCS #10: Certification Request Syntax Specification Version 1.7", RFC 2986, DOI 10.17487/RFC2986, , <https://www.rfc-editor.org/info/rfc2986>.
[RFC7797]
Jones, M., "JSON Web Signature (JWS) Unencoded Payload Option", RFC 7797, DOI 10.17487/RFC7797, , <https://www.rfc-editor.org/info/rfc7797>.
[RFC7800]
Jones, M., Bradley, J., and H. Tschofenig, "Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs)", RFC 7800, DOI 10.17487/RFC7800, , <https://www.rfc-editor.org/info/rfc7800>.
[RFC8747]
Jones, M., Seitz, L., Selander, G., Erdtman, S., and H. Tschofenig, "Proof-of-Possession Key Semantics for CBOR Web Tokens (CWTs)", RFC 8747, DOI 10.17487/RFC8747, , <https://www.rfc-editor.org/info/rfc8747>.
[RFC9449]
Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", RFC 9449, DOI 10.17487/RFC9449, , <https://www.rfc-editor.org/info/rfc9449>.
[RFC8785]
Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, DOI 10.17487/RFC8785, , <https://www.rfc-editor.org/info/rfc8785>.
[RFC8739]
Sheffer, Y., Lopez, D., Gonzalez de Dios, O., Pastor Perales, A., and T. Fossati, "Support for Short-Term, Automatically Renewed (STAR) Certificates in the Automated Certificate Management Environment (ACME)", RFC 8739, DOI 10.17487/RFC8739, , <https://www.rfc-editor.org/info/rfc8739>.

Appendix A. Open Questions for Working Group Discussion

This appendix summarizes design points that the authors believe would benefit from further WG discussion. These are not normative requirements, but rather an invitation for community feedback.

A.1. Challenge vs. New Mechanism

The current document models PoP as an ACME challenge ("pk-01"). An alternative approach, discussed on the WG mailing list, would introduce PoP as a new, out-of-band ACME mechanism — for example, a dedicated PoP endpoint or a reusable token — that separates PoP from the authorization challenge framework. Section 1.6 provides the rationale for the challenge-based approach. The WG is invited to comment on whether the challenge abstraction is the appropriate fit or whether a separate mechanism should be pursued.

A.2. KEM PoP and Certificate Revocation

KEM keys (e.g., ML-KEM) cannot produce signatures, which eliminates the "sign the revocation request with the certificate private key" path described in [RFC8555] Section 7.6. This limitation is not unique to ACME; it has been identified in other IETF working groups (notably LAMPS and COSE) as a cross-protocol challenge for post-quantum KEM certificates. As of this writing, no IETF standard or working group draft defines a dedicated KEM-based revocation mechanism. Common mitigation strategies across these communities include short-lived certificates (e.g., STAR [RFC8739]), account-level authentication for revocation requests, multi-factor authentication, and out-of-band revocation confirmation.

Section 7.5 of this document discusses the operational implications. The WG is invited to consider whether additional mechanisms (e.g., KEM-based revocation proofs) are necessary, or whether the mitigations described are sufficient for the deployment scenarios targeted by this document.

A.3. Algorithm Agility and Post-Quantum Readiness

Section 8.5 establishes an IANA registry for PoP Key Algorithms, enabling future algorithm additions without requiring a new RFC. The initial registry contents include algorithms defined in FIPS 203, FIPS 204, and FIPS 205. The WG is invited to discuss the scope of this registry: should it also cover future non-ML-KEM algorithms (e.g., Classic McEliece, BIKE, HQC) and their associated KEM PoP mechanisms? The current registry structure is extensible to any KEM or signature algorithm.

A.4. Multiple pk-01 Challenges and Key Consistency

The current document requires that all "pk-01" challenges in an order carry the same public key, and that servers include pk-01 in all authorizations when PoP is required. This symmetric treatment is specified in Section 4.1. The WG is invited to discuss whether this is always appropriate, or whether there are scenarios where PoP should be required only on a subset of authorizations (e.g., when one identifier is considered more security-critical than others).

A.5. popKeyAccepted Signal

The draft requires servers that use pk-01 to echo popKeyAccepted: true in the order object; servers that do not implement this specification will not include the field, and clients treat its absence as the fallback signal (see Section 3.3). Is this sufficient for clients to reliably detect fallback scenarios, or are there edge cases where a more explicit mechanism is needed?

A.6. Completeness of Deployment Scenarios

Section 1.1.1 describes deployment scenarios that motivate the "pk-01" challenge: KEM-only keys, resource-constrained IoT, identity/key attestation composition, and escrowed encryption keys. Additional scenarios noted during WG discussion include serverless/temporary workloads and privacy-enhanced deployments requiring fresh keys per order. The WG is invited to confirm that the described scenarios are sufficient to motivate adoption, and to identify any additional scenarios that would require changes to the protocol design.

A.7. popKey Reuse Across Orders

The current draft recommends that clients generate a fresh key pair for each order (Section 9.2). Should this recommendation be strengthened to a normative requirement (MUST NOT reuse), or is it acceptable to leave it as a non-normative recommendation to accommodate specific deployment patterns (e.g., pre-provisioned device keys that must remain stable across certificate renewals, such as TPM-bound keys)?

A.8. Alternatives to raw_newOrder Binding

The current draft binds PoP proofs to SHA-256(raw_newOrder), which requires the server to retain the raw JWS payload bytes. An alternative approach, discussed during WG review, would bind the proof to a canonicalized representation of the order's identifiers and public key (e.g., using JSON Canonicalization Scheme [RFC8785]), or to a server-assigned orderID. The former preserves the cryptographic binding to order content while eliminating the dependency on raw bytes; the latter simplifies implementation but weakens the binding to a server-maintained reference. The WG is invited to consider these alternatives based on deployment experience.

A.9. Scope Boundaries and Long-Term Evolution

This document defines a minimal PoP mechanism for ACME. It does not aim to solve every problem related to proof-of-possession, certificate revocation, or key management. The following topics are explicitly out of scope for this document and should be addressed by separate work items if the WG determines they are necessary:

  • KEM-based certificate revocation protocols.

  • Composite or hybrid signature schemes for PoP.

  • Integration with specific enterprise PKI deployments (e.g., AD CS, PKCS#11).

  • PoP mechanisms for protocols other than ACME.

The WG is invited to establish these scope boundaries to prevent unbounded expansion of this specification. Lessons from the evolution of X.509 suggest that protocols benefit from clear scope constraints applied early in their lifecycle.

A.10. Challenge Field Naming

The "pk-01" challenge object uses nonce as a field name, which overlaps terminologically with ACME's existing anti-replay machinery (the Replay-Nonce header and the nonce in the JWS protected header) and may confuse implementers. Existing [RFC8555] challenge types use token for challenge random values. The WG is invited to discuss whether this field should be renamed (e.g., popNonce, or following the token convention) to avoid ambiguity.

Appendix B. Appendix B. Document Revision History (Informative)

draft-geng-acme-public-key-00 (Initial Version): Initial publication. Introduced the concept of a public key challenge as an alternative to CSR-based finalization. Proposed multiple challenge variants bound to different identifier types.

draft-geng-acme-public-key-01: Minor editorial refinements. Clarified scope and relationship with existing ACME challenge types.

draft-geng-acme-public-key-02: Refined the challenge attachment model. Addressed early feedback on identifier binding semantics.

draft-geng-acme-public-key-03: Structural reorganization of challenge object fields. Improved alignment with RFC8555 terminology.

draft-geng-acme-public-key-04: Expanded challenge variants to six distinct types covering both PoP and identifier control validation. Introduced the pk_binding object in newOrder request. First draft to reference public key identity authentication protocols. Last combined version before functional split per IETF 125 feedback.

draft-geng-acme-public-key-05: Functional split: "pk-01" now focuses exclusively on proof-of-possession. Identifier control validation moved to draft-geng-acme-idp-01. Challenge consolidation into single pk-01 challenge. Introduced pop_mode negotiation and ALPN identifier acme-pk/1.

draft-geng-acme-public-key-06: Refined pop_mode semantics. Added comprehensive security considerations. Introduced initial KEM key support framework. WG adoption call issued (April 2026), did not pass due to architectural concerns regarding challenge semantics and insufficient community support.

draft-geng-acme-public-key-07: Removed pop_mode. "pk-01" became exclusively a proof-of-possession challenge. Added popKeyAccepted and popSupported fields. Established IANA "ACME PoP Key Algorithms" registry. Added KEM revocation guidance.

Authors' Addresses

Feng Geng
Huawei Technologies
Panyu Wu
Huawei Technologies
Liang Xia
Huawei Technologies
Xin Chen
TrustAsia