Network Working Group F. Denis Internet-Draft Individual Contributor Intended status: Informational 17 June 2026 Expires: 19 December 2026 The DNSCrypt Protocol draft-denis-dprive-dnscrypt-09 Abstract The DNSCrypt protocol is designed to encrypt and authenticate DNS traffic between clients and resolvers. This document specifies the protocol and its implementation, providing a standardized approach to securing DNS communications. DNSCrypt improves confidentiality, integrity, and resistance to attacks affecting the original DNS protocol while maintaining compatibility with existing DNS infrastructure. About This Document This note is to be removed before publishing as an RFC. The latest revision of this draft can be found at https://dnscrypt.github.io/dnscrypt-protocol/. Status information for this document may be found at https://datatracker.ietf.org/doc/ draft-denis-dprive-dnscrypt/. Source for this draft and an issue tracker can be found at https://github.com/DNSCrypt/dnscrypt-protocol. 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 19 December 2026. Denis Expires 19 December 2026 [Page 1] Internet-Draft DNSCrypt June 2026 Copyright Notice Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/ license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Table of Contents 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 2. Conventions And Definitions . . . . . . . . . . . . . . . . . 4 3. Protocol Flow . . . . . . . . . . . . . . . . . . . . . . . . 4 4. Protocol Components . . . . . . . . . . . . . . . . . . . . . 6 5. Protocol Description . . . . . . . . . . . . . . . . . . . . 8 5.1. Overview . . . . . . . . . . . . . . . . . . . . . . . . 9 5.2. Transport . . . . . . . . . . . . . . . . . . . . . . . . 10 5.3. Session Establishment . . . . . . . . . . . . . . . . . . 10 5.4. Query Processing . . . . . . . . . . . . . . . . . . . . 11 5.4.1. Padding For Client Queries Over UDP . . . . . . . . . 11 5.4.2. Client Queries Over UDP . . . . . . . . . . . . . . . 11 5.4.3. Padding For Client Queries Over TCP . . . . . . . . . 12 5.4.4. Client Queries Over TCP . . . . . . . . . . . . . . . 13 5.5. Certificates . . . . . . . . . . . . . . . . . . . . . . 13 6. Implementation Status . . . . . . . . . . . . . . . . . . . . 17 7. Security Considerations . . . . . . . . . . . . . . . . . . . 17 7.1. Protocol Security . . . . . . . . . . . . . . . . . . . . 17 7.2. Implementation Security . . . . . . . . . . . . . . . . . 18 7.3. Attack Mitigation . . . . . . . . . . . . . . . . . . . . 19 7.4. Privacy Considerations . . . . . . . . . . . . . . . . . 20 7.5. Operational Security . . . . . . . . . . . . . . . . . . 20 8. Operational Considerations . . . . . . . . . . . . . . . . . 21 9. Anonymized DNSCrypt . . . . . . . . . . . . . . . . . . . . . 22 9.1. Protocol Overview . . . . . . . . . . . . . . . . . . . . 22 9.2. Client Queries . . . . . . . . . . . . . . . . . . . . . 23 9.3. Relay Behavior . . . . . . . . . . . . . . . . . . . . . 24 9.4. Operational Considerations . . . . . . . . . . . . . . . 24 10. Post-Quantum Key Exchange (PQDNSCrypt) . . . . . . . . . . . 25 10.1. Key Encapsulation Instead of Key Agreement . . . . . . . 25 10.2. PQ Certificates . . . . . . . . . . . . . . . . . . . . 26 10.3. Certificate Retrieval Amplification . . . . . . . . . . 27 10.4. PQ Key Derivation . . . . . . . . . . . . . . . . . . . 28 10.5. PQ Query and Response Format . . . . . . . . . . . . . . 29 10.6. Padding and Transport . . . . . . . . . . . . . . . . . 30 10.7. Stateless Resumption . . . . . . . . . . . . . . . . . . 30 Denis Expires 19 December 2026 [Page 2] Internet-Draft DNSCrypt June 2026 10.7.1. Issuing a Ticket . . . . . . . . . . . . . . . . . . 30 10.7.2. Resuming . . . . . . . . . . . . . . . . . . . . . . 31 10.7.3. Resumption Considerations . . . . . . . . . . . . . 32 10.8. PQ and Anonymized DNSCrypt . . . . . . . . . . . . . . . 32 10.9. PQ Downgrade Protection . . . . . . . . . . . . . . . . 33 10.10. PQ Security Considerations . . . . . . . . . . . . . . . 33 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 34 12. Appendix 1: The Box-XChaChaPoly Algorithm . . . . . . . . . . 34 12.1. Conventions and Definitions . . . . . . . . . . . . . . 34 12.2. HChaCha20 . . . . . . . . . . . . . . . . . . . . . . . 34 12.3. Test Vector For The HChaCha20 Block Function . . . . . . 35 12.4. ChaCha20_DJB . . . . . . . . . . . . . . . . . . . . . . 35 12.5. XChaCha20_DJB . . . . . . . . . . . . . . . . . . . . . 35 12.6. XChaCha20_DJB-Poly1305 . . . . . . . . . . . . . . . . . 36 12.7. The Box-XChaChaPoly Algorithm . . . . . . . . . . . . . 37 13. Appendix 2: DNSCrypt Test Vectors . . . . . . . . . . . . . . 37 13.1. Pinned Inputs . . . . . . . . . . . . . . . . . . . . . 37 13.2. Public Keys and Shared Key . . . . . . . . . . . . . . . 39 13.3. Certificate . . . . . . . . . . . . . . . . . . . . . . 39 13.4. Client Query (UDP) . . . . . . . . . . . . . . . . . . . 40 13.5. Server Response (UDP) . . . . . . . . . . . . . . . . . 42 13.6. Padding and Transport Notes . . . . . . . . . . . . . . 43 13.7. Negative Cases . . . . . . . . . . . . . . . . . . . . . 43 14. Appendix 3: PQ Test Vector Structure . . . . . . . . . . . . 44 14.1. Provisional Assignments . . . . . . . . . . . . . . . . 44 14.2. Pinned Inputs . . . . . . . . . . . . . . . . . . . . . 45 14.3. Profile Extension and Signature Input . . . . . . . . . 46 14.4. Full X-Wing Query . . . . . . . . . . . . . . . . . . . 48 14.5. Full Response and Ticket Issuance . . . . . . . . . . . 49 14.6. Resumed Query and Response . . . . . . . . . . . . . . . 50 14.7. Negative Cases . . . . . . . . . . . . . . . . . . . . . 51 14.8. Generated Values . . . . . . . . . . . . . . . . . . . . 52 15. Normative References . . . . . . . . . . . . . . . . . . . . 54 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 55 1. Introduction The Domain Name System (DNS) [RFC1035] is a critical component of Internet infrastructure, but its original design did not include security features to protect the confidentiality and integrity of queries and responses. This fundamental security gap exposes DNS traffic to eavesdropping, tampering, and various attacks that can compromise user privacy and network security. To address these vulnerabilities, this document defines the DNSCrypt protocol, which encrypts and authenticates DNS queries and responses, providing strong confidentiality, integrity, and resistance to attacks affecting the original DNS protocol. The protocol is Denis Expires 19 December 2026 [Page 3] Internet-Draft DNSCrypt June 2026 designed to be lightweight, extensible, and simple to implement securely on top of existing DNS infrastructure, offering a practical solution for securing DNS communications without requiring significant changes to current systems. The following sections detail the protocol's design, starting with an overview of its operation and then progressing through the technical specifications needed for implementation. 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. 3. Protocol Flow The DNSCrypt protocol consists of two distinct phases: 1. *Initial Setup Phase* (one-time): * The client requests the server's certificate * The server responds with its certificate containing public keys 2. *Ongoing Communication Phase* (repeated as needed): * The client sends encrypted DNS queries * The server responds with encrypted DNS responses The following diagram illustrates the complete protocol flow: Denis Expires 19 December 2026 [Page 4] Internet-Draft DNSCrypt June 2026 +--------+ +--------+ | | | | | Client | | Server | | | | | +--------+ +--------+ | | | 1. Request Certificate | |---------------------------->| | | | 2. Certificate Response | |<----------------------------| | | | 3. Encrypted Query | |---------------------------->| | | | 4. Encrypted Query | |---------------------------->| | | | 5. Encrypted Response | |<----------------------------| | | | 6. Encrypted Response | |<----------------------------| | | | 7. Encrypted Query | |---------------------------->| | | | 8. Encrypted Response | |<----------------------------| | | | | The initial setup phase (steps 1-2) occurs only when: * A client first starts using a DNSCrypt server * The client's cached certificate expires * The client detects a certificate with a higher serial number After the initial setup, the client and server engage in the ongoing communication phase (steps 3-8), where encrypted queries and responses are exchanged as needed. This phase can be repeated indefinitely until the certificate expires or a new certificate is available. The ongoing communication phase operates with several important characteristics that distinguish it from traditional DNS: Denis Expires 19 December 2026 [Page 5] Internet-Draft DNSCrypt June 2026 1. *Stateless Operation*: Each query and response is independent. The server does not maintain state between queries. 2. *Out-of-Order Responses*: Responses may arrive in a different order than the queries were sent. Each response is self- contained and can be processed independently. 3. *Concurrent Queries*: A client can send multiple queries without waiting for earlier responses, and responses can be processed independently as they arrive. With this understanding of the protocol flow, we can now examine the specific components that make up DNSCrypt packets and their structure. 4. Protocol Components The DNSCrypt protocol defines specific packet structures for both client queries and server responses. These components work together to provide the security properties described in the previous section. Definitions for client queries: * : * : an 8 byte identifier for the resolver certificate chosen by the client. * : the client's public key, whose length depends on the encryption algorithm defined in the chosen certificate. * : the client's secret key. * : the resolver's public key. * : a unique query identifier for a given (, ) tuple. Every newly encrypted DNSCrypt query for the same (, ) tuple MUST use a distinct value, even when the plaintext DNS query is being retried. Retransmitting the same already-encrypted DNSCrypt packet does not require changing its nonce. The length of is determined by the chosen encryption algorithm. * AE: the authenticated encryption function. Denis Expires 19 December 2026 [Page 6] Internet-Draft DNSCrypt June 2026 * : AE( , ) * : the shared key derived from and , using the key exchange algorithm defined in the chosen certificate. * : the unencrypted client query. The query is not modified; in particular, the query flags are not altered. * : length is half the nonce length required by the encryption algorithm. In client queries, the other half, is filled with NUL bytes. * : the variable-length padding. Definitions for server responses: * : * : the 0x72 0x36 0x66 0x6e 0x76 0x57 0x6a 0x38 byte sequence * : * : the nonce sent by the client in the related query. * : the client's public key. * : the resolver's secret key. * : a unique response identifier for a given (, ) tuple. The length of depends on the chosen encryption algorithm. * AE: the authenticated encryption function. * : AE(, , ) * : the shared key derived from and , using the key exchange algorithm defined in the chosen certificate. * : the unencrypted resolver response. The response is not modified; in particular, the query flags are not altered. Denis Expires 19 December 2026 [Page 7] Internet-Draft DNSCrypt June 2026 * : the variable-length padding. The following diagram shows the structure of a DNSCrypt query packet: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Client Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Client Public Key + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Client Nonce + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Encrypted Query + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ The following diagram shows the structure of a DNSCrypt response packet: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Resolver Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Nonce + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Encrypted Response + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ These packet structures form the foundation for the protocol operations described in the next section, which details how clients and servers use these components to establish secure communications. 5. Protocol Description Denis Expires 19 December 2026 [Page 8] Internet-Draft DNSCrypt June 2026 5.1. Overview Building on the protocol flow and components described earlier, this section provides a detailed examination of how the DNSCrypt protocol operates. The protocol follows a well-defined sequence of steps: 1. The DNSCrypt client sends a DNS query to a DNSCrypt server to retrieve the server's public keys. 2. The client generates its own key pair. 3. The client encrypts unmodified DNS queries using a server's public key, padding them as necessary, and concatenates them to a nonce and a copy of the client's public key. The resulting output is transmitted to the server via standard DNS transport mechanisms [RFC1035]. 4. Encrypted queries are decrypted by the server using the attached client public key and the server's own secret key. The output is a regular DNS packet that doesn't require any special processing. 5. To send an encrypted response, the server adds padding to the unmodified response, encrypts the result using the shared key and a nonce made of the client's nonce followed by the resolver's nonce, and truncates the response if necessary. The resulting packet, truncated or not, is sent to the client using standard DNS mechanisms. 6. The client authenticates and decrypts the response using the shared key and the nonce included in the response. If the response was truncated, the client MAY adjust internal parameters and retry over TCP [RFC7766]. If not, the output is a regular DNS response that can be directly forwarded to applications and stub resolvers. Key features of the DNSCrypt protocol include: * Stateless operation: Every query can be processed independently from other queries, with no session identifiers required. * Flexible key management: Clients can replace their keys whenever they want, without extra interactions with servers. * Proxy support: DNSCrypt packets can securely be proxied without having to be decrypted, allowing client IP addresses to be hidden from resolvers ("Anonymized DNSCrypt"). Denis Expires 19 December 2026 [Page 9] Internet-Draft DNSCrypt June 2026 * Shared infrastructure: Recursive DNS servers can accept DNSCrypt queries on the same IP address and port used for regular DNS traffic. * Attack mitigation: DNSCrypt mitigates two common security vulnerabilities in regular DNS over UDP: amplification [RFC5358] and fragmentation attacks. These key features enable DNSCrypt to provide robust security while maintaining practical deployability. The protocol's transport characteristics further support these goals. 5.2. Transport The DNSCrypt protocol can use the UDP and TCP transport protocols. DNSCrypt clients and resolvers SHOULD support the protocol via UDP, and MUST support it over TCP. Both TCP and UDP connections using DNSCrypt SHOULD employ port 443 by default. The choice of port 443 helps DNSCrypt traffic blend with HTTPS traffic, providing some protection against traffic analysis. Once transport is established, the next step is session establishment through certificate exchange. 5.3. Session Establishment From the client's perspective, a DNSCrypt session is initiated when the client sends an unauthenticated DNS query to a DNSCrypt-capable resolver. This DNS query contains encoded information about the certificate versions supported by the client and a public identifier of the desired provider. The resolver sends back a collection of signed certificates that the client MUST verify using the pre-distributed provider public key. Each certificate includes a validity period, a serial number, a version that defines a key exchange mechanism, an authenticated encryption algorithm and its parameters, as well as a short-term public key, known as the resolver public key. Resolvers have the ability to support various algorithms and can concurrently advertise multiple short-term public keys (resolver public keys). The client picks the one with the highest serial number among the currently valid ones that match a supported protocol version. Denis Expires 19 December 2026 [Page 10] Internet-Draft DNSCrypt June 2026 Every certificate contains a unique magic number that the client MUST include at the beginning of their queries. This allows the resolver to identify which certificate the client selected for crafting a particular query. The encryption algorithm, resolver public key, and client magic number from the chosen certificate are then used by the client to send encrypted queries. These queries include the client public key. With the knowledge of the chosen certificate and corresponding secret key, along with the client's public key, the resolver is able to verify, decrypt the query, and then encrypt the response utilizing identical parameters. Once the session is established through certificate exchange, the ongoing query processing follows specific rules for different transport protocols and padding requirements. 5.4. Query Processing 5.4.1. Padding For Client Queries Over UDP Before encryption takes place, queries are padded according to the ISO/IEC 7816-4 standard. Padding begins with a single byte holding the value 0x80, followed by any number of NUL bytes. MUST be at least bytes. In this context, represents the original client query, while denotes the added padding. Should the client query's length fall short of bytes, the padding length MUST be adjusted in order to satisfy the length requirement. is a variable length, initially set to 256 bytes, and MUST be a multiple of 64 bytes. It represents the minimum permitted length for a client query, inclusive of padding. 5.4.2. Client Queries Over UDP UDP-based client queries need to follow the padding guidelines outlined in the previous section. Each UDP packet MUST hold one query, with the complete content comprising the structure specified in the Protocol Components section. Denis Expires 19 December 2026 [Page 11] Internet-Draft DNSCrypt June 2026 UDP packets employing the DNSCrypt protocol have the capability to be split into distinct IP packets sharing the same source port. Upon receiving a query, the resolver may choose to either disregard it or send back a response encrypted using DNSCrypt. The client MUST authenticate and, if authentication succeeds, decrypt the response with the help of the resolver's public key, the shared secret, and the response nonce. The client MUST verify that the prefix of the response nonce matches a currently outstanding query. In case the response fails verification, or the does not match a currently outstanding query, it MUST be disregarded by the client. If the response has the TC flag set, the client MUST: 1. send the query again using TCP [RFC7766] 2. set the new minimum query length as: ::= min( + 64, ) denotes the minimum permitted length for a client query, including padding. That value MUST be capped so that the full length of a DNSCrypt packet doesn't exceed the maximum size required by the transport layer. The client MAY decrease , but the length MUST remain a multiple of 64 bytes. While UDP queries require careful length management due to truncation concerns, TCP queries follow different padding rules due to the reliable nature of the transport. 5.4.3. Padding For Client Queries Over TCP Queries MUST undergo padding using the ISO/IEC 7816-4 format before being encrypted. The padding starts with a byte valued 0x80 followed by a variable number of NUL bytes. The length of is selected randomly, ranging from 1 to 256 bytes, including the initial byte valued at 0x80. The total length of MUST be a multiple of 64 bytes. For example, an originally unpadded 56-bytes DNS query can be padded as: Denis Expires 19 December 2026 [Page 12] Internet-Draft DNSCrypt June 2026 <56-bytes-query> 0x80 0x00 0x00 0x00 0x00 0x00 0x00 0x00 or <56-bytes-query> 0x80 (0x00 * 71) or <56-bytes-query> 0x80 (0x00 * 135) or <56-bytes-query> 0x80 (0x00 * 199) 5.4.4. Client Queries Over TCP The sole differences between encrypted client queries transmitted via TCP and those sent using UDP lie in the padding length calculation and the inclusion of a two-byte big-endian length prefix for the encrypted DNSCrypt packet. Unlike UDP queries, a query sent over TCP can be shorter than the response. After having received a response from the resolver, the client and the resolver MUST close the TCP connection to ensure security and comply with this revision of the protocol, which prohibits multiple transactions over the same TCP connection. The query processing rules described above depend on the certificate information obtained during session establishment. The certificate format and management procedures are critical to the protocol's security. 5.5. Certificates The following diagram shows the structure of a DNSCrypt certificate: Denis Expires 19 December 2026 [Page 13] Internet-Draft DNSCrypt June 2026 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Cert Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ES Version | Protocol Minor Version | Reserved | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Signature + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Resolver Public Key + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Client Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Serial | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | TS Start | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | TS End | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Extensions + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ To initiate a DNSCrypt session, a client transmits an ordinary unencrypted TXT DNS query to the resolver's IP address and DNSCrypt port. The attempt is first made using UDP; if unsuccessful due to failure, timeout, or truncation, the client then proceeds with TCP. Resolvers are not required to serve certificates both on UDP and TCP. The name in the question () MUST follow this scheme: . dnscrypt-cert . A major protocol version has only one certificate format. A DNSCrypt client implementing the second version of the protocol MUST send a query with the TXT type and a name of the form: 2.dnscrypt-cert.example.com The zone MUST be a valid DNS name, but MAY not be registered in the DNS hierarchy. Denis Expires 19 December 2026 [Page 14] Internet-Draft DNSCrypt June 2026 A single provider name can be shared by multiple resolvers operated by the same entity, and a resolver can respond to multiple provider names, especially to support multiple protocol versions simultaneously. In order to use a DNSCrypt-enabled resolver, a client must know the following information: * The resolver IP address and port * The provider name * The provider public key The provider public key is a long-term key whose sole purpose is to verify the certificates. It is never used to encrypt or verify DNS queries. A single provider public key can be employed to sign multiple certificates. For example, an organization operating multiple resolvers can use a unique provider name and provider public key across all resolvers, and just provide a list of IP addresses and ports. Each resolver MAY have its unique set of certificates that can be signed with the same key. It is RECOMMENDED that certificates are signed using specialized hardware rather than directly on the resolvers themselves. Once signed, resolvers SHOULD make these certificates available to clients. Signing certificates on dedicated hardware helps ensure security and integrity, as it isolates the process from potential vulnerabilities present in the resolver's system. A successful response to a certificate request contains one or more TXT records, each record containing a certificate encoded as follows: * : * : 0x44 0x4e 0x53 0x43 * : the cryptographic construction to use with this certificate. For Box-XChaChaPoly, MUST be 0x00 0x02. * : 0x00 0x00 Denis Expires 19 December 2026 [Page 15] Internet-Draft DNSCrypt June 2026 * : a 64-byte signature of ( ) using the Ed25519 algorithm and the provider secret key. Ed25519 MUST be used in this version of the protocol. * : the resolver short-term public key, which is 32 bytes when using X25519. * : The first 8 bytes of a client query that was built using the information from this certificate. It MAY be a truncated public key. Two valid certificates cannot share the same . MUST NOT start with 0x00 0x00 0x00 0x00 0x00 0x00 0x00 (seven all-zero bytes) in order to avoid confusion with the QUIC protocol [RFC9000]. * : a 4-byte serial number in big-endian format. If more than one certificate is valid, the client MUST prefer the certificate with a higher serial number. * : the date the certificate is valid from, as a big- endian 4-byte unsigned Unix timestamp. * : the date the certificate is valid until (inclusive), as a big-endian 4-byte unsigned Unix timestamp. * : empty in the current protocol version, but may contain additional data in future revisions, including minor versions. The computation and verification of the signature MUST include the extensions. An implementation not supporting these extensions MUST ignore them. Certificates made of this information, without extensions, are 116 bytes long. With the addition of , , and , the record is 124 bytes long. After receiving a set of certificates, the client checks their validity based on the current date, filters out the ones designed for encryption systems that are not supported by the client, and chooses the certificate with the higher serial number. DNSCrypt queries sent by the client MUST use the header of the chosen certificate, as well as the specified encryption system and public key. The client MUST check for new certificates every hour and switch to a new certificate if: * The current certificate is not present or not valid anymore, Denis Expires 19 December 2026 [Page 16] Internet-Draft DNSCrypt June 2026 or * A certificate with a higher serial number than the current one is available. The certificate management system ensures that cryptographic keys remain fresh and that clients can smoothly transition to updated certificates. With the core protocol mechanics now established, we can examine implementation considerations. 6. Implementation Status _Note: This section is to be removed before publishing as an RFC._ Multiple implementations of the protocol described in this document have been developed and verified for interoperability. A comprehensive list of known implementations can be found at https://dnscrypt.info/implementations. The successful deployment of multiple interoperable implementations demonstrates the protocol's maturity. However, proper implementation requires careful attention to security considerations. 7. Security Considerations This section discusses security considerations for the DNSCrypt protocol. 7.1. Protocol Security The DNSCrypt protocol provides several security benefits: 1. *Confidentiality*: DNS queries and responses are encrypted using XChaCha20-Poly1305 [RFC8439], preventing eavesdropping of DNS traffic. For example, a query for "example.com" would be encrypted and appear as random data to an observer. 2. *Integrity*: Message authentication using Poly1305 [RFC8439] ensures that responses cannot be tampered with in transit. Any modification to the encrypted response would be detected and rejected by the client. 3. *Authentication*: The use of X25519 [RFC7748] for key exchange and Ed25519 for certificate signatures provides strong authentication of resolvers. Clients can verify they are communicating with the intended resolver and not an impostor. Denis Expires 19 December 2026 [Page 17] Internet-Draft DNSCrypt June 2026 4. *Short-Term Resolver Keys*: Resolver certificates carry short- term public keys, limiting the impact of key compromise and enabling regular key rotation. These fundamental security properties depend on correct implementation practices. Several implementation-specific security aspects require particular attention. 7.2. Implementation Security Implementations should consider the following security aspects: 1. *Key Management*: * Resolvers MUST rotate their short-term key pairs at most every 24 hours * Previous secret keys MUST be discarded after rotation * Provider secret keys used for certificate signing SHOULD be stored in hardware security modules (HSMs) * Example: A resolver might generate new key pairs daily at midnight UTC 2. *Nonce Management*: * Nonces MUST NOT be reused for a given shared secret * Clients SHOULD generate values using either a cryptographically secure random number generator with enough entropy to make collisions negligible for the lifetime of the shared secret, or a secret-key pseudorandom construction, such as encrypting a timestamp and any counter or random bits needed for uniqueness using a block cipher. Such constructions MUST NOT expose wall-clock time or other stable client state to observers, and MUST still provide nonce uniqueness for the lifetime of the shared secret * Clients SHOULD NOT include unencrypted timestamps in nonce values, especially when Anonymized DNSCrypt, Tor, SOCKS, or other proxying or anonymity systems are used * Clients can quickly discard stale responses by keeping local state for outstanding queries, including their values and expiration deadlines, and rejecting responses for nonces that are unknown, already answered, or expired Denis Expires 19 December 2026 [Page 18] Internet-Draft DNSCrypt June 2026 3. *Padding*: * Implementations MUST use the specified padding scheme to prevent traffic analysis * The minimum query length SHOULD be adjusted based on network conditions * Example: A 50-byte query might be padded to 256 bytes to prevent size-based fingerprinting 4. *Certificate Validation*: * Clients MUST verify certificate signatures using the provider's public key * Certificates MUST be checked for validity periods * Clients MUST prefer certificates with higher serial numbers * Example: A client might cache valid certificates and check for updates hourly Proper implementation of these security measures provides the foundation for the protocol's attack mitigation capabilities. 7.3. Attack Mitigation DNSCrypt provides protection against several types of attacks: 1. *DNS Spoofing*: The use of authenticated encryption prevents spoofed responses. An attacker cannot forge responses without the server's secret key. 2. *Amplification Attacks*: The padding requirements and minimum query length help prevent amplification attacks [RFC5358]. For example, a 256-byte minimum query size limits the amplification factor. 3. *Fragmentation Attacks*: The protocol mitigates fragmentation risks by padding queries, allowing truncated UDP responses, and retrying over TCP when necessary. 4. *Replay Exposure Reduction*: Nonces make responses query- specific. Clients can discard late, duplicate, or unrelated responses by checking the returned against local outstanding-query state and request deadlines, without exposing timestamps in plaintext nonce values. Denis Expires 19 December 2026 [Page 19] Internet-Draft DNSCrypt June 2026 While DNSCrypt effectively mitigates these attacks, implementers should also be aware of privacy considerations that extend beyond basic protocol security. 7.4. Privacy Considerations While DNSCrypt encrypts DNS traffic, there are some privacy considerations: 1. *Resolver Knowledge*: Resolvers can still see the client's IP address unless Anonymized DNSCrypt is used. This can reveal the client's location and network. 2. *Query Patterns*: Even with encryption, the size and timing of queries may reveal information. Padding helps mitigate this but doesn't eliminate it completely. 3. *Nonce Metadata*: Client nonces are visible on the wire. Encoding unencrypted timestamps or other stable or linkable state in nonce values can disclose clock information or support client fingerprinting, particularly when relays or anonymity networks are used. Clients SHOULD prefer nonce constructions that reveal no wall-clock time to observers. 4. *Certificate Requests*: Initial certificate requests are unencrypted but only return public data. This is a one-time exposure per session. These privacy considerations complement the security measures and should inform operational practices for DNSCrypt deployments. 7.5. Operational Security Operators should consider: 1. *Key Distribution*: Provider public keys should be distributed securely to clients. This might involve: * Publishing keys on secure websites * Using DNSSEC-signed records * Including keys in software distributions 2. *Certificate Management*: Certificates should be signed on dedicated hardware, not on resolvers. This provides: * Better key protection Denis Expires 19 December 2026 [Page 20] Internet-Draft DNSCrypt June 2026 * Centralized certificate management * Reduced attack surface 3. *Access Control*: Resolvers may implement access control based on client public keys. This can: * Prevent abuse * Enable service differentiation * Support business models 4. *Monitoring*: Operators should monitor for unusual patterns that may indicate attacks: * High query rates from single clients * Unusual query patterns * Certificate request anomalies These operational security practices work together with the technical security measures to provide comprehensive protection. Additional operational considerations extend beyond security to include practical deployment aspects. 8. Operational Considerations Special attention should be paid to the uniqueness of the generated secret keys. Client public keys can be used by resolvers to authenticate clients, link queries to customer accounts, and unlock business-specific features such as redirecting specific domain names to a sinkhole. Resolvers accessible from any client IP address can also opt for only responding to a set of whitelisted public keys. Resolvers accepting queries from any client MUST accept any client public key. In particular, an anonymous client can generate a new key pair for every session, or even for every query. This mitigates the ability for a resolver to group queries by client public keys and discover the set of IP addresses a user might have been operating. Denis Expires 19 December 2026 [Page 21] Internet-Draft DNSCrypt June 2026 Resolvers MUST rotate the short-term key pair every 24 hours at most, and MUST throw away the previous secret key. After a key rotation, a resolver MUST still accept all the previous keys that haven't expired. Provider public keys MAY be published as DNSSEC-signed TXT records [RFC1035], in the same zone as the provider name. For example, a query for the TXT type on the name "2.pubkey.example.com" may return a signed record containing a hexadecimal-encoded provider public key for the provider name "2.dnscrypt-cert.example.com". As a client is likely to reuse the same key pair many times, servers are encouraged to cache shared keys instead of performing the X25519 operation for each query. This makes the computational overhead of DNSCrypt negligible compared to plain DNS. While DNSCrypt provides strong encryption and authentication, some use cases require additional privacy protection. The Anonymized DNSCrypt extension addresses scenarios where hiding client IP addresses from resolvers is necessary. 9. Anonymized DNSCrypt While DNSCrypt encrypts DNS traffic, DNS server operators can still observe client IP addresses. Anonymized DNSCrypt is an extension to the DNSCrypt protocol that allows queries and responses to be relayed by an intermediate server, hiding the client's IP address from the resolver. This extension maintains all the security properties of standard DNSCrypt while adding an additional layer of privacy protection. 9.1. Protocol Overview Anonymized DNSCrypt works by having the client send encrypted queries to a relay server, which then forwards them to the actual DNSCrypt resolver. The relay server cannot decrypt the queries or responses, and the resolver only sees the relay's IP address. [Client]----(encrypted query)--->[Relay]----(encrypted query)--->[Server] [Client]<--(encrypted response)--[Relay]<--(encrypted response)--[Server] Key properties of Anonymized DNSCrypt: * The relay cannot decrypt or modify queries and responses * The resolver only sees the relay's IP address, not the client's Denis Expires 19 December 2026 [Page 22] Internet-Draft DNSCrypt June 2026 * A DNSCrypt server can simultaneously act as a relay * The protocol works over both UDP and TCP 9.2. Client Queries The following diagram shows the structure of an Anonymized DNSCrypt query packet: 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Anon Magic | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | + Server IP (IPv6) + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Server Port | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + DNSCrypt Query + | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ An Anonymized DNSCrypt query is a standard DNSCrypt query prefixed with information about the target server: ::= Where: * : 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x00 0x00 * : 16 bytes encoded IPv6 address (IPv4 addresses are mapped to IPv6 using ::ffff: [RFC4291]) * : 2 bytes in big-endian format * : standard DNSCrypt query For example, a query for a server at 192.0.2.1:443 would be prefixed with: 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xff 0xff 0xc0 0x00 0x02 0x01 0x01 0xbb Denis Expires 19 December 2026 [Page 23] Internet-Draft DNSCrypt June 2026 9.3. Relay Behavior Relays MUST: 1. Accept queries over both TCP and UDP 2. Communicate with upstream servers over UDP, even if client queries were sent over TCP 3. Validate incoming packets: * Check that the target IP is not in a private range [RFC1918] * Verify the port number is in an allowed range * Ensure the DNSCrypt query doesn't start with * Verify the query doesn't start with 7 zero bytes (to avoid confusion with QUIC [RFC9000]) 4. Forward valid queries unmodified to the server 5. Verify server responses: * For encrypted DNSCrypt responses, check that the response is smaller than the query * For certificate responses, check that the response transaction ID and query name match the relayed certificate query * Validate the response format (either starts with resolver magic or is a certificate response) * Forward valid responses unmodified to the client These relay requirements ensure that anonymization does not compromise the security properties of the underlying DNSCrypt protocol. Proper deployment requires additional operational considerations. 9.4. Operational Considerations When using Anonymized DNSCrypt: 1. Clients should choose relays and servers operated by different entities 2. Having relays and servers on different networks is recommended Denis Expires 19 December 2026 [Page 24] Internet-Draft DNSCrypt June 2026 3. Relay operators should: * Refuse forwarding to reserved IP ranges [RFC1918] * Restrict allowed server ports (typically only allowing port 443) * Monitor for abuse These operational guidelines help ensure that Anonymized DNSCrypt deployments provide the intended privacy benefits while maintaining security and preventing abuse. 10. Post-Quantum Key Exchange (PQDNSCrypt) The key exchange described so far relies on X25519 [RFC7748], which a sufficiently capable quantum computer would be able to break. An attacker who records DNSCrypt traffic today could therefore decrypt it once such a computer exists. This section defines the PQ extension, which performs the key exchange with a hybrid post-quantum mechanism while leaving the rest of the protocol unchanged: the certificate system, the packet framing, the authenticated encryption, the nonces, the padding philosophy, and Anonymized DNSCrypt all carry over. A DNSCrypt deployment that uses this extension is referred to as PQDNSCrypt. PQ is introduced as a new encryption system version ( 0x00 0x03) inside the existing version 2 certificate format. It is not a new major protocol version, and it does not change the certificate lookup name. A resolver MAY advertise a PQ certificate alongside a classical certificate under the same provider name, and a client that does not implement PQ ignores the value it does not recognize, exactly as already required. The values that PQ introduces, namely the , the resume magic, the ticket parameters, and the profile identifiers, are provisional assignments used by this document and by the test vectors in Appendix 3. They are expected to be confirmed before publication. 10.1. Key Encapsulation Instead of Key Agreement Classical DNSCrypt uses a non-interactive key agreement: the resolver publishes an X25519 public key in its certificate, the client places its own X25519 public key in , and both sides compute the same shared secret. A post-quantum key encapsulation mechanism (KEM) does not offer a non-interactive key agreement, but it fits the same single-message exchange. The resolver generates a KEM key pair and publishes the public (encapsulation) key in the field Denis Expires 19 December 2026 [Page 25] Internet-Draft DNSCrypt June 2026 of its certificate. The client runs the KEM encapsulation against , obtaining a ciphertext and a shared secret, and places the ciphertext in the field. The resolver runs the KEM decapsulation on the received ciphertext using its secret key and recovers the same shared secret. The field therefore carries a KEM ciphertext rather than a client public key, and its length is determined by the of the chosen certificate. The resolver remains stateless: it derives the shared secret from a single client message, with no per- client state. Everything after the shared secret is shared with classical DNSCrypt, with the small additions described in this section. PQ uses X-Wing [I-D.connolly-cfrg-xwing-kem], a hybrid KEM that combines ML-KEM-768 [FIPS203] with X25519 [RFC7748]. Being a hybrid, the shared secret remains secure as long as either ML-KEM-768 or X25519 is unbroken, which protects against both a future quantum break of X25519 and an unexpected weakness in ML-KEM-768. The X-Wing encapsulation key is 1216 bytes, the ciphertext is 1120 bytes, and the shared secret is 32 bytes. 10.2. PQ Certificates A PQ certificate uses the version 2 certificate format without modification. The field is 0x00 0x03, and the field holds the 1216-byte X-Wing encapsulation key. The retains its role as a unique 8-byte certificate selector that MUST NOT begin with seven zero bytes; because a KEM ciphertext is freshly generated for every query, is an opaque identifier and is never a truncated public key. The Ed25519 signature input is unchanged. It MUST cover ( ), exactly as for classical certificates, so that provider signing procedures do not require a second code path. The PQ profile metadata is authenticated through the already-signed field, which for a PQ certificate contains a profile extension: ::= "PQD" Denis Expires 19 December 2026 [Page 26] Internet-Draft DNSCrypt June 2026 where is 0x01, is 0x01 for HKDF-SHA256 [RFC5869], is 0x01 for the XChaCha20_DJB-Poly1305 construction of Appendix 1, and and are the encapsulation-key and ciphertext lengths as two-byte big-endian integers. A client implementing PQ MUST require this extension on a PQ certificate and MUST reject the certificate if the on the wire or the field lengths disagree with the signed copies in the extension. The existing signature already provides implicit integrity for , because is signed and its length follows from : altering the version shifts the signed region and causes verification to fail, as long as distinct encryption systems use distinct lengths. The signed profile extension makes the binding explicit and preserves it should a future encryption system reuse an existing length. PQ certificates are approximately 1.3 KB before DNS TXT record framing. A single 1320-byte PQ certificate requires six TXT character-strings and therefore about 1338 bytes as one answer RR; a response containing one classical 124-byte certificate and one PQ certificate is typically about 1.5 KB, depending on the provider name. A response with two classical certificates and two PQ certificates is typically about 3.0 KB. A response with one classical certificate and three PQ certificates will normally exceed 4096 octets. A certificate response that contains a PQ certificate exceeds 512 bytes, so retrieval relies on EDNS(0) [RFC6891], TCP [RFC7766], or both. A 4096-octet DNS response is a useful upper bound for certificate responses, but it is not a fragmentation-avoidance target. Operators that need maximum UDP robustness SHOULD use a lower target; however, one PQ certificate already exceeds the common 1232-octet UDP payload target once DNS framing is included. 10.3. Certificate Retrieval Amplification Certificate retrieval is an unauthenticated DNS query, and PQ certificates are much larger than classical ones, so a resolver that returns one or more PQ certificates over UDP can be abused as a traffic amplifier in response to queries with a spoofed source address. Resolvers MUST NOT send a UDP certificate response larger than the requestor's advertised EDNS(0) UDP payload size, or larger than 512 octets when no EDNS(0) UDP payload size is advertised, and SHOULD keep certificate responses below 4096 octets even when a larger value is advertised. Denis Expires 19 December 2026 [Page 27] Internet-Draft DNSCrypt June 2026 Anonymized DNSCrypt relays forward certificate queries to upstream resolvers over UDP, even when the client-to-relay connection uses TCP. Therefore, a resolver that wants PQ certificate discovery to work reliably through existing relays SHOULD make the complete certificate set fit in a UDP response, instead of assuming that the client can obtain the PQ certificates through TCP fallback on the same relay path. For relay-compatible PQ deployments, resolvers SHOULD use the following UDP certificate sets: * Normal steady state: one classical certificate and one PQ certificate. * Rollover window: two classical certificates and two PQ certificates. Resolvers SHOULD NOT exceed the rollover certificate set over UDP. If the complete certificate response would exceed these limits, the resolver SHOULD set the TC flag and rely on the client retrying over TCP [RFC7766]. When it does so, the resolver SHOULD still include the smaller classical certificate in the truncated UDP response, so that a client that does not implement PQ can proceed without a second round trip while a PQ-capable client learns that more certificates may be available over TCP. Operators MAY serve a small classical certificate over UDP while requiring TCP for larger PQ certificate sets. This affects neither the certificate format nor the lookup name. Because a resolver can withhold PQ certificates from a truncated UDP response, a PQ-capable client MUST honor the TC flag on a certificate response and retry the certificate query over TCP when TCP to the resolver is available. A client that ignores the TC flag would only ever observe the certificates present in the UDP response and could silently fail to use PQ even against a resolver that supports it. 10.4. PQ Key Derivation For a PQ query, the shared secret is the 32-byte X-Wing shared secret. It is not used directly as the encryption key. Instead, both parties derive with HKDF-SHA256 [RFC5869], binding the certificate context and the ciphertext: Denis Expires 19 December 2026 [Page 28] Internet-Draft DNSCrypt June 2026 cert-context ::= "DNSCrypt-PQ-v1" ::= HKDF-SHA256(IKM = , salt = , info = cert-context , L = 32) where is the X-Wing shared secret and is the content of the field, that is, the X-Wing ciphertext. Binding and separates keys across certificates and any future encryption system; binding , , and the validity timestamps ties the key to the exact signed certificate; binding ties it to the precise encapsulation. The derived is then used with the XChaCha20_DJB-Poly1305 construction of Appendix 1 and the existing 24-byte nonce construction: 12 client-chosen bytes followed by 12 zero bytes for queries, and 12 client-chosen bytes followed by 12 resolver-chosen bytes for responses. 10.5. PQ Query and Response Format A PQ query uses the structure without modification; only the length of changes, to the 1120-byte X-Wing ciphertext. A PQ response uses the structure without modification on the wire, but the decrypted payload begins with a short control block ahead of the unmodified DNS response: ::= is a two-byte big-endian length. When it is zero, is absent and the DNS response begins immediately after the length. When it is nonzero, carries PQ control data, currently a stateless resumption ticket. The response padding is computed over the whole plaintext, so the decrypted payload keeps the usual length alignment. A PQ client removes the control block after decryption and forwards the unmodified DNS response. Because the shared secret is symmetric, the resolver needs no additional KEM operation to encrypt a response. Denis Expires 19 December 2026 [Page 29] Internet-Draft DNSCrypt June 2026 10.6. Padding and Transport A PQ query that carries a ciphertext includes roughly 1.1 KB in , so it is always far larger than its response. The minimum query length defined for client queries over UDP exists to prevent amplification, and that concern does not apply to a query that is already this large. A PQ query that carries a ciphertext is therefore NOT subject to the 256-byte minimum: it is padded only to the next multiple of 64 bytes. A resumed query, described below, carries a small ticket instead of a ciphertext, so it MUST use the regular minimum query length, initially 256 bytes, as in classical DNSCrypt. PQ queries and responses MUST be supported over TCP [RFC7766], and TCP is a first-class transport for PQ rather than only a fallback. A client SHOULD use a configurable UDP payload size target, 1232 bytes by default, and SHOULD use TCP when a query would exceed it. A PQ query that carries a ciphertext is approximately 1220 bytes, which fits within a single unfragmented datagram on common paths but can exceed 1232 bytes once the Anonymized DNSCrypt prefix is added; in that case the client SHOULD use TCP. 10.7. Stateless Resumption Performing a KEM decapsulation for every query is significantly more expensive than the classical X25519 operation, and because every ciphertext is distinct there is no shared-key cache to amortize it. To control this cost without keeping per-client state, PQ defines stateless resumption: after an initial query that carries a ciphertext, the resolver issues an opaque ticket that lets subsequent queries skip both the ciphertext and the decapsulation. A resolver maintains one or more server-wide ticket keys, denoted TK. A TK is shared by all processes answering for a given certificate and is rotated independently of client traffic. A resolver MAY retain a previous TK for a short overlap so that outstanding tickets continue to verify, but the overlap MUST NOT exceed the advertised ticket lifetime. 10.7.1. Issuing a Ticket After a PQ query that carries a ciphertext has been decrypted, both parties hold . They derive a resumption secret: resume-secret ::= HKDF-SHA256(IKM = , salt = , info = "DNSCrypt-PQ-resume-secret-v1", L = 32) Denis Expires 19 December 2026 [Page 30] Internet-Draft DNSCrypt June 2026 The resolver seals the resumption secret and the metadata needed to validate it later under TK: ticket-plain ::= resume-secret ticket ::= AE(TK, , ticket-plain) The ticket is opaque, resolver-private state: its internal format and AEAD are an implementation choice and never need to interoperate between resolvers. This document's reference construction reuses the XChaCha20_DJB-Poly1305 AEAD of Appendix 1 with no associated data; selects the ticket key, so its integrity follows from decryption failing under the wrong key, and a dedicated TK keeps ticket sealing separate from query traffic. The client stores the ticket together with the resume-secret it derived and the ticket expiry. The ticket is delivered in the response control block: ::= "PQDR" A resolver SHOULD issue a ticket in the first PQ response and MAY renew it on later responses; a client SHOULD adopt the most recent valid ticket it receives. A captured ticket is of no use on its own: deriving the per-query key requires either the resume-secret, which only the client holds, or TK, which only the resolver holds. 10.7.2. Resuming A resumed query uses a distinct packet form, with the resume magic in place of and the ticket in place of : ::= is a reserved 8-byte value that MUST NOT collide with any valid , with , with the Anonymized DNSCrypt , or with seven leading zero bytes. On receiving a resumed query, the resolver locates the ticket key from , opens the ticket, and rejects the query if the ticket cannot be opened, is expired, or if any sealed certificate- context field does not match an acceptable current certificate. The sealed certificate-context fields are , , , , and ; is compared to SHA-256() for the matched certificate. It then derives the per-query key: Denis Expires 19 December 2026 [Page 31] Internet-Draft DNSCrypt June 2026 ::= HKDF-SHA256(IKM = resume-secret, salt = , info = "DNSCrypt-PQ-resumed-query-v1" SHA-256(), L = 32) The client performs the same derivation. The nonce construction is unchanged. Each resumed query thus uses a fresh key derived from its own ; clients MUST still use a distinct for each resumed query, because repeating it would repeat both the key and the AEAD nonce. If a ticket cannot be opened or validated, the resolver MUST silently drop the query, with no response distinguishable from any other dropped query. A client that receives no response retries with a query that carries a ciphertext, obtaining a fresh ticket. 10.7.3. Resumption Considerations A ticket bounds forward secrecy for resumed traffic: compromise of TK exposes only the resumed queries whose tickets are still valid under that ticket-key epoch, and never the queries that carried a ciphertext. The ticket lifetime SHOULD be short and MUST NOT exceed the resolver certificate lifetime or the ticket-key lifetime. A ticket is also a linkable handle for its lifetime; a client that prioritizes unlinkability, in particular over Anonymized DNSCrypt, SHOULD send queries that carry a ciphertext rather than resuming. Resumed queries are replayable to the same extent as any stateless DNSCrypt query, and clients discard stale or duplicate responses with outstanding-query nonce tracking as usual. A resolver implementing PQ SHOULD support ticket issuance and resumption, since high query volumes make per-query decapsulation costly. A resolver SHOULD rate-limit decapsulation of queries that carry a ciphertext and prioritize valid resumed traffic under load. 10.8. PQ and Anonymized DNSCrypt Anonymized DNSCrypt relays forward opaque DNSCrypt queries and require no changes for PQ. A query that carries a ciphertext keeps the classical query shape with a larger field, and a resumed query uses the resume shape above; both are opaque to a relay. The relay check that an encrypted response is smaller than the query is satisfied automatically for queries that carry a ciphertext, because they are large. A resumed query is small, so a client using Anonymized DNSCrypt MUST keep enough padding on a resumed UDP query for the relay's encrypted-response size check to pass, or send it over TCP. Denis Expires 19 December 2026 [Page 32] Internet-Draft DNSCrypt June 2026 Certificate retrieval through a relay is different: the relay forwards the certificate query to the resolver over UDP and forwards a matching certificate response back to the client. PQ-capable resolvers that want to be reachable through relays therefore SHOULD follow the UDP certificate response size recommendations in Certificate Retrieval Amplification. 10.9. PQ Downgrade Protection An on-path attacker cannot forge a certificate, but it can drop the PQ records from an unauthenticated certificate response, leaving only a classical certificate and pushing the client onto a quantum- vulnerable exchange. A signature cannot prevent deletion. A client that has been provisioned with the knowledge that a resolver supports PQ, for example through a flag in the DNS stamp that already carries the provider name and public key, MUST NOT fall back to a classical for that resolver. A client without such provisioning MAY fall back, accepting the classical risk. 10.10. PQ Security Considerations Confidentiality against a future quantum adversary holds as long as either ML-KEM-768 or X25519 is unbroken, because X-Wing is a hybrid. Resolver authentication is as in classical DNSCrypt: the client encapsulates to a signed encapsulation key, and only the holder of the corresponding secret key can recover the shared secret and produce an authenticated response. The KEM ciphertext is not separately authenticated and does not need to be. X-Wing, through ML-KEM-768, uses implicit rejection: a malformed but correctly sized ciphertext yields a pseudo-random shared secret rather than an error, so a tampered ciphertext produces a different key and authentication fails. A resolver MUST drop such a query exactly as it drops any query that fails authentication, and the outcome on the wire MUST NOT reveal, through a distinct response, error, or timing, whether decapsulation, key derivation, or authentication failed; otherwise the resolver becomes a decapsulation oracle. KEM and X25519 operations SHOULD be constant-time with respect to secret data. Forward secrecy for queries that carry a ciphertext has the same granularity as classical resolver-key rotation, since the resolver KEM key is short-term and the client's encapsulation randomness is fresh per query. Resumed queries inherit the shorter of the ticket lifetime and the ticket-key lifetime. Denis Expires 19 December 2026 [Page 33] Internet-Draft DNSCrypt June 2026 Nonce uniqueness is required as in classical DNSCrypt. For queries that carry a ciphertext, each has an independent key, so cross-query collisions cannot occur; for resumed queries the per-query key derivation uses , so clients MUST keep it unique for the lifetime of a ticket. 11. IANA Considerations This document has no IANA actions. 12. Appendix 1: The Box-XChaChaPoly Algorithm The Box-XChaChaPoly algorithm combines the X25519 [RFC7748] key exchange mechanism with a variant of the ChaCha20-Poly1305 construction specified in [RFC8439]. 12.1. Conventions and Definitions * x[a..]: the subarray of x starting at index a, and extending to the last index of x * x[a..b]: the subarray of x starting at index a and ending at index b. * LOAD32_LE(p): returns a 32-bit unsigned integer from the 4-byte array p * STORE32_LE(p, x): stores the 32-bit unsigned integer x into the 4-byte array p 12.2. HChaCha20 HChaCha20 is based on the construction and security proof used to create XSalsa20, an extended-nonce variant of Salsa20. The HChaCha20 function takes the following input parameters: * : secret key * : a 128-bit input and returns a 256-bit keyed hash. The function can be implemented using an existing IETF-compliant ChaCha20 implementation as follows: Denis Expires 19 December 2026 [Page 34] Internet-Draft DNSCrypt June 2026 block_bytes = ChaCha20(msg={0}**64, nonce=in[4..16], counter=LOAD32_LE(in[0..4]), key=k) block_out[0] = LOAD32_LE(block_bytes[ 0..][0..4]) - 0x61707865 block_out[1] = LOAD32_LE(block_bytes[ 4..][0..4]) - 0x3320646e block_out[2] = LOAD32_LE(block_bytes[ 8..][0..4]) - 0x79622d32 block_out[3] = LOAD32_LE(block_bytes[12..][0..4]) - 0x6b206574 block_out[4] = LOAD32_LE(block_bytes[48..][0..4]) - LOAD32_LE(in[ 0..][0..4]) block_out[5] = LOAD32_LE(block_bytes[52..][0..4]) - LOAD32_LE(in[ 4..][0..4]) block_out[6] = LOAD32_LE(block_bytes[56..][0..4]) - LOAD32_LE(in[ 8..][0..4]) block_out[7] = LOAD32_LE(block_bytes[60..][0..4]) - LOAD32_LE(in[12..][0..4]) for i in 0..8: STORE32_LE(out[i * 4..][0..4], block_out[i]) return out 12.3. Test Vector For The HChaCha20 Block Function k: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f in: 000102030405060708090a0b0c0d0e0f out: 51e3ff45a895675c4b33b46c64f4a9ace110d34df6a2ceab486372bacbd3eff6 12.4. ChaCha20_DJB As opposed to the version standardized for IETF protocols, ChaCha20 was originally designed to have a 8 byte nonce. For the needs of TLS, [RFC8439] changed this by setting N_MIN and N_MAX to 12, at the expense of a smaller internal counter. DNSCrypt uses ChaCha20 as originally specified, with N_MIN = N_MAX = 8. We refer to this variant as ChaCha20_DJB. The internal counter in ChaCha20_DJB is 4 bytes larger than ChaCha20. There are no other differences between ChaCha20_DJB and ChaCha20. 12.5. XChaCha20_DJB XChaCha20_DJB can be constructed from an existing ChaCha20 implementation and the HChaCha20 function. Denis Expires 19 December 2026 [Page 35] Internet-Draft DNSCrypt June 2026 All that needs to be done is: 1. Pass the key and the first 16 bytes of the 24-byte nonce to HChaCha20 to obtain the subkey. 2. Use the subkey and remaining 8 byte nonce with ChaCha20_DJB. 12.6. XChaCha20_DJB-Poly1305 XChaCha20 is a stream cipher and offers no integrity guarantees without being combined with a MAC algorithm (e.g. Poly1305). XChaCha20_DJB-Poly1305 adds an authentication tag to the ciphertext encrypted with XChaCha20_DJB. It is the combined mode used by the NaCl secretbox and crypto_box constructions, instantiated with XChaCha20_DJB. The one-time Poly1305 key is taken from the start of the keystream, and the message is encrypted with the keystream that immediately follows it. No separate keystream block is reserved for the Poly1305 key, so this layout differs from the AEAD of [RFC8439], where the message starts at block counter 1 and the rest of the first keystream block is discarded. Concretely, for a key and a message : * : encryption key * : message to encrypt * : the XChaCha20_DJB keystream produced from and the 24-byte nonce, starting at block counter 0. * : [0..32], the one-time Poly1305 key. These bytes are not transmitted. * : XOR [32..32 + length()], the ciphertext. * : Poly1305(, ), the 16-byte tag. * XChaCha20_DJB-Poly1305(, ): || Equivalently, XChaCha20_DJB is run over the buffer || , where is 32 NUL bytes, starting at block counter 0; the first 32 output bytes are taken as , and the remaining length() bytes are . Denis Expires 19 December 2026 [Page 36] Internet-Draft DNSCrypt June 2026 12.7. The Box-XChaChaPoly Algorithm The Box-XChaChaPoly algorithm combines the key exchange mechanism X25519 defined [RFC7748] with the XChaCha20_DJB-Poly1305 authenticated encryption algorithm. * : encryption key * : message to encrypt * : recipient's public key * : sender's secret key * : 16 NUL bytes * : HChaCha20(X25519(, ), ), the shared key * Box-XChaChaPoly(pk, sk, m): XChaCha20_DJB-Poly1305(, ) 13. Appendix 2: DNSCrypt Test Vectors This appendix provides complete, reproducible test vectors for the regular DNSCrypt protocol with the Box-XChaChaPoly encryption system of Appendix 1, that is, 0x00 0x02: X25519 key exchange, the XChaCha20_DJB-Poly1305 AEAD, and Ed25519 certificate signatures. All randomness is pinned so the vectors are reproducible. Every value is given in full as a hexadecimal string, wrapped to 32 bytes per line. The field and byte order of each artifact matches the Protocol Components and Certificates sections. These vectors were cross-checked byte for byte against the dnscrypt-proxy reference implementation. 13.1. Pinned Inputs The secret keys below are the raw 32-byte X25519 scalars as stored by an implementation; X25519 clamps them internally. The provider signing key is given as its 32-byte Ed25519 seed. Denis Expires 19 December 2026 [Page 37] Internet-Draft DNSCrypt June 2026 +===============================+========+=========================+ | Input | Length | Value | +===============================+========+=========================+ | provider Ed25519 signing seed | 32 | 00 01 02 ... 1f | +-------------------------------+--------+-------------------------+ | resolver X25519 secret key | 32 | 20 21 22 ... 3f | +-------------------------------+--------+-------------------------+ | client X25519 secret key | 32 | 40 41 42 ... 5f | +-------------------------------+--------+-------------------------+ | | 8 | b1 b2 b3 b4 b5 b6 b7 b8 | +-------------------------------+--------+-------------------------+ | | 2 | 00 02 | +-------------------------------+--------+-------------------------+ | | 2 | 00 00 | +-------------------------------+--------+-------------------------+ | | 4 | 00 00 00 01 | +-------------------------------+--------+-------------------------+ | | 4 | 68 00 00 00 | +-------------------------------+--------+-------------------------+ | | 4 | 68 01 51 80 | +-------------------------------+--------+-------------------------+ | query | 12 | a0 a1 a2 ... ab | +-------------------------------+--------+-------------------------+ | response | 12 | c0 c1 c2 ... cb | +-------------------------------+--------+-------------------------+ | | 0 | empty | +-------------------------------+--------+-------------------------+ Table 1 is chosen by the resolver and carried in the certificate; the client copies it verbatim into the first 8 bytes of every query. and span exactly 86400 seconds (a one-day validity window). The fixed protocol constants are = 44 4e 53 43, = 00 02, and = 72 36 66 6e 76 57 6a 38. The example DNS messages are a query and its answer for www.example.com: dns-query (33 bytes), id 0x1234, RD set, A? www.example.com IN: 12340100000100000000000003777777076578616d706c6503636f6d00000100 01 dns-response (49 bytes), A 93.184.216.34, TTL 3600: 12348180000100010000000003777777076578616d706c6503636f6d00000100 01c00c0001000100000e1000045db8d822 Denis Expires 19 December 2026 [Page 38] Internet-Draft DNSCrypt June 2026 13.2. Public Keys and Shared Key provider-ed25519-pk = Ed25519 public key for the signing seed: 03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8 resolver-pk = X25519 base-point mult of the resolver secret key: 358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254 client-pk = X25519 base-point mult of the client secret key: 79a631eede1bf9c98f12032cdeadd0e7a079398fc786b88cc846ec89af85a51a x25519-shared-point = X25519(client-sk, resolver-pk) = X25519(resolver-sk, client-pk): 04c304fb1ca83cee75e206344231f33797e07d9929db670994b7c6fbeb1dc255 shared-key = HChaCha20(key = x25519-shared-point, in = 16 NUL bytes): 335d32f2d65e6623cbbd05b6539c9575fee16cb5405fe839ab4bd291fdf13262 The same shared-key is computed by the client from (client-sk, resolver-pk) and by the resolver from (resolver-sk, client-pk). 13.3. Certificate The signature covers , with empty in this protocol version: signed input (52 bytes): 358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254 b1b2b3b4b5b6b7b8000000016800000068015180 signature = Ed25519.Sign(provider signing seed, signed input) (64 bytes): 3a570ea17f47b80217977fbb455840bfd50ab32f5fbf2aabc173a6a49b7a49ca 55362a6c5dec47657cf515e9f99382a316dfecd964b94d1c4659cac45961400c The full certificate, as carried in a TXT record, is 124 bytes: Denis Expires 19 December 2026 [Page 39] Internet-Draft DNSCrypt June 2026 +========+==========================+========+=================+ | Offset | Field | Length | Value | +========+==========================+========+=================+ | 0 | | 4 | 44 4e 53 43 | +--------+--------------------------+--------+-----------------+ | 4 | | 2 | 00 02 | +--------+--------------------------+--------+-----------------+ | 6 | | 2 | 00 00 | +--------+--------------------------+--------+-----------------+ | 8 | | 64 | 3a 57 ... 40 0c | +--------+--------------------------+--------+-----------------+ | 72 | | 32 | 35 80 ... 62 54 | +--------+--------------------------+--------+-----------------+ | 104 | | 8 | b1 b2 b3 b4 b5 | | | | | b6 b7 b8 | +--------+--------------------------+--------+-----------------+ | 112 | | 4 | 00 00 00 01 | +--------+--------------------------+--------+-----------------+ | 116 | | 4 | 68 00 00 00 | +--------+--------------------------+--------+-----------------+ | 120 | | 4 | 68 01 51 80 | +--------+--------------------------+--------+-----------------+ Table 2 certificate (124 bytes): 444e5343000200003a570ea17f47b80217977fbb455840bfd50ab32f5fbf2aab c173a6a49b7a49ca55362a6c5dec47657cf515e9f99382a316dfecd964b94d1c 4659cac45961400c358072d6365880d1aeea329adf9121383851ed21a28e3b75 e965d0d2cd166254b1b2b3b4b5b6b7b8000000016800000068015180 13.4. Client Query (UDP) The plaintext is the DNS query padded with ISO/IEC 7816-4 to = 256 bytes: one 0x80 byte followed by NUL bytes. The 24-byte AEAD nonce is the 12-byte client nonce followed by 12 NUL bytes. Denis Expires 19 December 2026 [Page 40] Internet-Draft DNSCrypt June 2026 padded query plaintext (256 bytes): 12340100000100000000000003777777076578616d706c6503636f6d00000100 0180000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 query AEAD nonce (24 bytes): a0a1a2a3a4a5a6a7a8a9aaab000000000000000000000000 encrypted-query = tag (16) || ciphertext (256) (272 bytes): 2dae527c26386d5cd4e61152db6dd1812ff6aaf7644fc122afc70b1b580b18f1 0fbc26577abc759152cde31cd0afc5c5f452f8654815469723300819bed5a120 15c044b94d63ec1f79e48a23968e437feb8bb8720cf4e60a0499746190c8b3eb 83aeb0d858df77794270b861f86644502be0d22d6f0b2b132e9ca68538300c8d 68b8e3c48190cbbf96d602f38dfc3b4d642016ceeaf4bc2c2ded9483b9f9d4ee d703a0bebc252add8822d4b9152e30670bcde9ea75a0e3e67ea576e9b1262bb2 b25b4f9432311b75a2238b34bf4f868da182b85dccb1762a703bba31d04d77b4 c57ec9039663959793677588b3a74ae409b0f16374dd64cbd6d47d801725b014 ce9ddaf6f1aa30688c8efcbfde1d5d1d Query on the wire (324 bytes): +========+===================+========+=========================+ | Offset | Field | Length | Value | +========+===================+========+=========================+ | 0 | | 8 | b1 b2 b3 b4 b5 b6 b7 b8 | +--------+-------------------+--------+-------------------------+ | 8 | | 32 | 79 a6 ... a5 1a | +--------+-------------------+--------+-------------------------+ | 40 | | 12 | a0 a1 ... ab | +--------+-------------------+--------+-------------------------+ | 52 | | 272 | 2d ae ... d5 1d | +--------+-------------------+--------+-------------------------+ Table 3 Denis Expires 19 December 2026 [Page 41] Internet-Draft DNSCrypt June 2026 full query wire (324 bytes): b1b2b3b4b5b6b7b879a631eede1bf9c98f12032cdeadd0e7a079398fc786b88c c846ec89af85a51aa0a1a2a3a4a5a6a7a8a9aaab2dae527c26386d5cd4e61152 db6dd1812ff6aaf7644fc122afc70b1b580b18f10fbc26577abc759152cde31c d0afc5c5f452f8654815469723300819bed5a12015c044b94d63ec1f79e48a23 968e437feb8bb8720cf4e60a0499746190c8b3eb83aeb0d858df77794270b861 f86644502be0d22d6f0b2b132e9ca68538300c8d68b8e3c48190cbbf96d602f3 8dfc3b4d642016ceeaf4bc2c2ded9483b9f9d4eed703a0bebc252add8822d4b9 152e30670bcde9ea75a0e3e67ea576e9b1262bb2b25b4f9432311b75a2238b34 bf4f868da182b85dccb1762a703bba31d04d77b4c57ec9039663959793677588 b3a74ae409b0f16374dd64cbd6d47d801725b014ce9ddaf6f1aa30688c8efcbf de1d5d1d 13.5. Server Response (UDP) The plaintext is the DNS response padded with ISO/IEC 7816-4 to 64 bytes. The 24-byte AEAD nonce is the client nonce followed by the resolver nonce. padded response plaintext (64 bytes): 12348180000100010000000003777777076578616d706c6503636f6d00000100 01c00c0001000100000e1000045db8d822800000000000000000000000000000 response AEAD nonce (24 bytes): a0a1a2a3a4a5a6a7a8a9aaabc0c1c2c3c4c5c6c7c8c9cacb encrypted-response = tag (16) || ciphertext (64) (80 bytes): f2670995c6d37c2f8d2016029dd5970b893de83c02815ece9b48d9fd0b0dca87 41674142fbd8e12c1120b111f366326aa71c89823a2931ac5c860dad49685ed6 cc22cc13e829d2e51d1c00ea64d1d39d Response on the wire (112 bytes): +========+======================+========+=========================+ | Offset | Field | Length | Value | +========+======================+========+=========================+ | 0 | | 8 | 72 36 66 6e 76 57 6a 38 | +--------+----------------------+--------+-------------------------+ | 8 | | 24 | a0..ab (client) c0..cb | | | | | (resolver) | +--------+----------------------+--------+-------------------------+ | 32 | | 80 | f2 67 ... d3 9d | +--------+----------------------+--------+-------------------------+ Table 4 Denis Expires 19 December 2026 [Page 42] Internet-Draft DNSCrypt June 2026 full response wire (112 bytes): 7236666e76576a38a0a1a2a3a4a5a6a7a8a9aaabc0c1c2c3c4c5c6c7c8c9cacb f2670995c6d37c2f8d2016029dd5970b893de83c02815ece9b48d9fd0b0dca87 41674142fbd8e12c1120b111f366326aa71c89823a2931ac5c860dad49685ed6 cc22cc13e829d2e51d1c00ea64d1d39d 13.6. Padding and Transport Notes The vectors fix the padded plaintext lengths so they are reproducible: * The query plaintext is padded to = 256 bytes, the minimum permitted length for a client query inclusive of padding and a multiple of 64. An implementation MAY use a larger that is also a multiple of 64; dnscrypt-proxy defaults to 512. * The response plaintext is padded to the smallest multiple of 64 that holds the response plus at least one padding byte, here 64 bytes. The exact response padding length is otherwise an implementation choice, subject to the response being no larger than the query over UDP. * Over TCP the encryption is identical, but each packet is prefixed with a two-byte big-endian length, and the query padding length is chosen at random as described in Query Processing. 13.7. Negative Cases These vectors pin the required failure behavior. None of them produce a distinguishable on-the-wire signal beyond "no response" or "certificate rejected". 1. Tampered ciphertext: flipping any byte of or makes Poly1305 verification fail. The receiver MUST drop the packet. 2. Bad padding: after a successful decryption, the plaintext MUST end with a 0x80 byte followed by zero or more NUL bytes. A plaintext that does not MUST be rejected. 3. Wrong : a query whose first 8 bytes do not match the of any certificate the resolver currently serves is not a DNSCrypt query for this resolver. The resolver MUST NOT treat it as one. Denis Expires 19 December 2026 [Page 43] Internet-Draft DNSCrypt June 2026 4. Response nonce mismatch: the client MUST verify that the prefix (first 12 bytes) of the response nonce matches an outstanding query, and otherwise drop the response. 5. Weak public key: if the X25519 shared point is the all-zero value, the public key is of low order and the shared key MUST be rejected. 6. Certificate outside its validity window: a certificate whose / does not include the current time MUST NOT be used, and among valid certificates the client picks the highest . 14. Appendix 3: PQ Test Vector Structure This appendix fixes the exact field order and byte order for PQ. Long cryptographic outputs, namely KEM keys and ciphertexts, the Ed25519 signature, AEAD outputs, and HKDF outputs, are left as placeholders to be filled in by a reference implementation. Everything structural is pinned here, so that two implementations cannot disagree about layout even before the hex values exist. All integers are big-endian. Every AEAD operation is XChaCha20_DJB- Poly1305 as defined in Appendix 1, with the 16-byte tag prepended to the ciphertext. Every key derivation is HKDF-SHA256 [RFC5869]. Placeholders are written [name: N bytes]; the concrete values they stand for appear in the Generated Values subsection at the end of this appendix. 14.1. Provisional Assignments The following values are the provisional assignments used by these vectors. They are normative for the vectors but expected to be confirmed before publication. Denis Expires 19 December 2026 [Page 44] Internet-Draft DNSCrypt June 2026 +==========================+=======================================+ | Item | Value | +==========================+=======================================+ | (X-Wing) | 0x00 0x03 | +--------------------------+---------------------------------------+ | | 50 51 52 65 73 75 6d 65 ("PQResume") | +--------------------------+---------------------------------------+ | | 0x01 (HKDF-SHA256) | +--------------------------+---------------------------------------+ | | 0x01 (XChaCha20_DJB-Poly1305) | +--------------------------+---------------------------------------+ | ticket AEAD | XChaCha20_DJB-Poly1305, 24-byte nonce | +--------------------------+---------------------------------------+ | | 4 bytes | +--------------------------+---------------------------------------+ | | 24 bytes | +--------------------------+---------------------------------------+ | | 4-byte Unix timestamp | +--------------------------+---------------------------------------+ | | 4-byte seconds | +--------------------------+---------------------------------------+ | | SHA-256(), 32 bytes | +--------------------------+---------------------------------------+ Table 5 14.2. Pinned Inputs All randomness is fixed so the vectors are reproducible. Short values are given concretely; values produced by a primitive are placeholders. +===============================+========+=========================+ | Input | Length | Value | +===============================+========+=========================+ | provider Ed25519 signing seed | 32 | 00 01 02 ... 1f | +-------------------------------+--------+-------------------------+ | provider Ed25519 public key | 32 | [provider-pk: 32 bytes] | +-------------------------------+--------+-------------------------+ | resolver X-Wing secret seed | 32 | 20 21 22 ... 3f | +-------------------------------+--------+-------------------------+ | resolver X-Wing public key | 1216 | [resolver-pk: 1216 | | | | bytes] | +-------------------------------+--------+-------------------------+ | client X-Wing encapsulation | 64 | 40 41 42 ... 7f | | seed | | | +-------------------------------+--------+-------------------------+ | | 2 | 00 03 | Denis Expires 19 December 2026 [Page 45] Internet-Draft DNSCrypt June 2026 +-------------------------------+--------+-------------------------+ | | 2 | 00 00 | +-------------------------------+--------+-------------------------+ | | 8 | a1 b2 c3 d4 e5 f6 07 18 | +-------------------------------+--------+-------------------------+ | | 4 | 00 00 00 01 | +-------------------------------+--------+-------------------------+ | | 4 | 68 00 00 00 | +-------------------------------+--------+-------------------------+ | | 4 | 68 01 51 80 | +-------------------------------+--------+-------------------------+ | query | 12 | b0 b1 b2 ... bb | +-------------------------------+--------+-------------------------+ | response | 12 | c0 c1 c2 ... cb | +-------------------------------+--------+-------------------------+ | ticket key TK | 32 | 80 81 82 ... 9f | +-------------------------------+--------+-------------------------+ | | 4 | 00 00 00 01 | +-------------------------------+--------+-------------------------+ | | 24 | d0 d1 d2 ... e7 | +-------------------------------+--------+-------------------------+ | | 4 | 68 00 02 58 | +-------------------------------+--------+-------------------------+ | | 4 | 00 00 01 2c | +-------------------------------+--------+-------------------------+ | resumed | 12 | f0 f1 f2 ... fb | +-------------------------------+--------+-------------------------+ | resumed | 12 | 10 11 12 ... 1b | +-------------------------------+--------+-------------------------+ | example DNS query (A? | 33 | [dns-query: 33 bytes] | | www.example.com) | | | +-------------------------------+--------+-------------------------+ | example DNS response | var | [dns-response] | +-------------------------------+--------+-------------------------+ Table 6 14.3. Profile Extension and Signature Input The PQ profile extension is the entire field in this revision: Denis Expires 19 December 2026 [Page 46] Internet-Draft DNSCrypt June 2026 pq-profile-ext = "PQD" 50 51 44 ext-version 01 es-version 00 03 kdf-id 01 (HKDF-SHA256) aead-id 01 (XChaCha20_DJB-Poly1305) resolver-pk-len 04 c0 (1216) client-kex-len 04 60 (1120) -> 12 bytes total The Ed25519 signature is computed over the existing field set, unchanged: sig-input = resolver-pk (1216) || client-magic (8) || serial (4) || ts-start (4) || ts-end (4) || extensions (12) -> 1248 bytes signature = Ed25519.Sign(provider-seed, sig-input) = [signature: 64 bytes] The full certificate (92 fixed bytes + 1216-byte resolver key + 12-byte extensions = 1320 bytes): Denis Expires 19 December 2026 [Page 47] Internet-Draft DNSCrypt June 2026 +========+==========================+========+===================+ | Offset | Field | Length | Value | +========+==========================+========+===================+ | 0 | | 4 | 44 4e 53 43 | +--------+--------------------------+--------+-------------------+ | 4 | | 2 | 00 03 | +--------+--------------------------+--------+-------------------+ | 6 | | 2 | 00 00 | +--------+--------------------------+--------+-------------------+ | 8 | | 64 | [signature: 64 | | | | | bytes] | +--------+--------------------------+--------+-------------------+ | 72 | | 1216 | [resolver-pk: | | | | | 1216 bytes] | +--------+--------------------------+--------+-------------------+ | 1288 | | 8 | a1 b2 c3 d4 e5 f6 | | | | | 07 18 | +--------+--------------------------+--------+-------------------+ | 1296 | | 4 | 00 00 00 01 | +--------+--------------------------+--------+-------------------+ | 1300 | | 4 | 68 00 00 00 | +--------+--------------------------+--------+-------------------+ | 1304 | | 4 | 68 01 51 80 | +--------+--------------------------+--------+-------------------+ | 1308 | | 12 | 50 51 44 01 00 03 | | | | | 01 01 04 c0 04 60 | +--------+--------------------------+--------+-------------------+ Table 7 14.4. Full X-Wing Query Denis Expires 19 December 2026 [Page 48] Internet-Draft DNSCrypt June 2026 (resolver-pk, resolver-sk) = X-Wing.GenerateKeyPairDerand(resolver-seed) (ct, kem-ss) = X-Wing.EncapsulateDerand(resolver-pk, eseed) ct = [ct: 1120 bytes] kem-ss = [kem-ss: 32 bytes] cert-context = "DNSCrypt-PQ-v1" (14 bytes) || es-version (00 03) || protocol-minor-version (00 00) || resolver-pk (1216) || client-magic (8) || serial (4) || ts-start (4) || ts-end (4) || extensions (12) shared-key = HKDF-SHA256( IKM = kem-ss, salt = es-version || client-magic (10 bytes: 00 03 a1 b2 c3 d4 e5 f6 07 18), info = cert-context || ct, L = 32) = [shared-key: 32 bytes] query-nonce = client-nonce || (12 * 00) (24 bytes) plaintext = dns-query (33) || 80 || (30 * 00) (padded to 64; ISO/IEC 7816-4) encrypted-query = tag (16) || ciphertext (64) = [enc-query: 80 bytes] Query on the wire (1220 bytes): +========+===================+========+=========================+ | Offset | Field | Length | Value | +========+===================+========+=========================+ | 0 | | 8 | a1 b2 c3 d4 e5 f6 07 18 | +--------+-------------------+--------+-------------------------+ | 8 | = ct | 1120 | [ct: 1120 bytes] | +--------+-------------------+--------+-------------------------+ | 1128 | | 12 | b0 b1 ... bb | +--------+-------------------+--------+-------------------------+ | 1140 | | 80 | [enc-query: 80 bytes] | +--------+-------------------+--------+-------------------------+ Table 8 14.5. Full Response and Ticket Issuance Denis Expires 19 December 2026 [Page 49] Internet-Draft DNSCrypt June 2026 resume-secret = HKDF-SHA256( IKM = shared-key, salt = client-magic || client-nonce (20 bytes), info = "DNSCrypt-PQ-resume-secret-v1", L = 32) = [resume-secret: 32 bytes] profile-extension-hash = SHA-256(extensions) = [peh: 32 bytes] ticket-plain = resume-secret (32) || es-version (2) || client-magic (8) || serial (4) || ts-end (4) || ticket-expiry (4) || profile-extension-hash (32) (86 bytes) ticket = ticket-key-id (4) || ticket-nonce (24) || AE(TK, ticket-nonce, ticket-plain) where AE output = tag (16) || ciphertext (86) -> 4 + 24 + 102 = 130 bytes = [ticket: 130 bytes] control = "PQDR" (50 51 44 52) || control-version (01) || ticket-lifetime (00 00 01 2c) || ticket-len (00 82) || ticket (130) (141 bytes) pq-response-plain = control-len (00 8d) || control (141) || dns-response || pad-to-64 response-nonce = client-nonce || resolver-nonce (24 bytes) encrypted-response = tag (16) || ciphertext = [enc-response] Response on the wire: +======================+========+===================================+ | Field | Length | Value | +======================+========+===================================+ | | 8 | 72 36 66 6e 76 57 6a 38 | +----------------------+--------+-----------------------------------+ | | 24 | b0..bb (client) c0..cb | | | | (resolver) | +----------------------+--------+-----------------------------------+ | | var | [enc-response] | +----------------------+--------+-----------------------------------+ Table 9 14.6. Resumed Query and Response Denis Expires 19 December 2026 [Page 50] Internet-Draft DNSCrypt June 2026 resumed shared-key = HKDF-SHA256( IKM = resume-secret, salt = client-magic || resumed-client-nonce (20 bytes), info = "DNSCrypt-PQ-resumed-query-v1" || SHA-256(ticket), L = 32) = [resumed-shared-key: 32 bytes] query-nonce = resumed-client-nonce || (12 * 00) (24 bytes) plaintext = dns-query || 80 || pad (padded to 256: resumed floor) encrypted-query = tag (16) || ciphertext (256) = [enc-query: 272 bytes] Resumed query on the wire (424 bytes): +========+===================+========+=========================+ | Offset | Field | Length | Value | +========+===================+========+=========================+ | 0 | | 8 | 50 51 52 65 73 75 6d 65 | +--------+-------------------+--------+-------------------------+ | 8 | | 2 | 00 82 (130) | +--------+-------------------+--------+-------------------------+ | 10 | | 130 | [ticket: 130 bytes] | +--------+-------------------+--------+-------------------------+ | 140 | | 12 | f0 f1 ... fb | +--------+-------------------+--------+-------------------------+ | 152 | | 272 | [enc-query: 272 bytes] | +--------+-------------------+--------+-------------------------+ Table 10 The resumed response reuses resumed shared-key with nonce resumed- client-nonce || resumed-resolver-nonce. If the resolver issues no new ticket, the control block is empty (control-len = 00 00). 14.7. Negative Cases These vectors pin the required failure behavior. None of them produce a distinguishable on-the-wire signal beyond "no response" or "certificate rejected". 1. Bad profile-extension length: resolver-pk-len or client-kex-len in the extension disagrees with the actual field length, or pq- profile-ext is not 12 bytes. The client MUST reject the certificate. 2. mismatch: the on-the-wire differs from the copy inside the signed extension. The client MUST reject the certificate. Denis Expires 19 December 2026 [Page 51] Internet-Draft DNSCrypt June 2026 3. Corrupted ticket AEAD: one byte of the sealed region of in a resumed query is flipped. AEAD opening fails, and the resolver MUST silently drop the query. 4. Expired or rotated ticket: is in the past, or names a TK that has been rotated out. The resolver MUST silently drop the query; the client re-handshakes with a query that carries a ciphertext. 5. Ticket context mismatch: any sealed certificate-context field in the ticket (, , , , or ) does not match the resumption context. The resolver MUST silently drop the query. 6. Malformed KEM ciphertext: one byte of in a query that carries a ciphertext is flipped. X-Wing implicit rejection yields a different shared secret, authentication fails, and the resolver MUST silently drop the query, with no distinct error or timing. 7. Repeated nonce (client obligation): reusing a under one ticket reuses both the derived key and the AEAD nonce; this is a client MUST NOT. A stateless resolver cannot detect it, so there is no wire vector; it is listed to make the obligation explicit. 8. Under-padded resumed query: a resumed UDP query padded below the 256-byte floor decrypts correctly but violates the anti- amplification rule, and an Anonymized DNSCrypt relay MAY drop it on the response-size check. 14.8. Generated Values The values below were produced by a reference generator from the pinned inputs above, and are reproducible by any conformant implementation. Values up to 141 bytes are given in full; longer artifacts are pinned by their SHA-256 digest. The generator self- checks against the HChaCha20 known-answer test of Appendix 1 and the official X-Wing known-answer test, and verifies that X-Wing decapsulation recovers the encapsulated secret. provider-ed25519-pk (32): 03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8 resolver-pk (1216, SHA-256): a1f324bc0701f1234fbba7b11901023b3644f3bb8c6eb4ee4368d7e859eb6228 client-kex / ct (1120, SHA-256): f6bf3f238e83f24cd444f2887e8fd32d630e07dbe6ca2f2b403aaf5333030c48 kem-ss (32): Denis Expires 19 December 2026 [Page 52] Internet-Draft DNSCrypt June 2026 8dac8602d4ce5e27e81335b54b25fdcaea86e56613214ee0522db4a5e0a38d50 shared-key (32): e6d4ab9cffc9b49e2a64d80d7eb2dde280f806b89e834d596ad385b1dd75e9ef signature (64): 811bab04e2e70c9d946296a93b4028d7c7bb84f32f597d3cf8aba29edc1b6b97 4acc99dd00ec62cdcae477433d10bff20e1c432e1011ad8ad5324f68a294750c dns-query (33): 12340100000100000000000003777777076578616d706c6503636f6d00000100 01 dns-response (49): 12348180000100010000000003777777076578616d706c6503636f6d00000100 01c00c0001000100000e1000045db8d822 padded query plaintext (64): 12340100000100000000000003777777076578616d706c6503636f6d00000100 0180000000000000000000000000000000000000000000000000000000000000 encrypted-query (80): c41764468cb42d3a837c51234c08be714af49e1a6830ea6da28178e9e280d76b ac1b87fd7f56515f2b2cc3d4715aaa42907c282db1edff0bc3b92cd535a710e2 64859a5bdaf67c17ffa6e1c6f6e02a50 full query wire (1220, SHA-256): 65c3421776283f503779916e7b5c32d0d41c885508ad892b349688db6c901233 resume-secret (32): df158804e3f8ddf383ff7c9d3128491b29437a894936ec72c68aed8a9553272b profile-extension-hash = SHA-256(extensions) (32): fab3bf4996c5d2fdfc330ec958d0a5b63624bf3fbdc0fedfa9d94b0941a4060c ticket-plain (86): df158804e3f8ddf383ff7c9d3128491b29437a894936ec72c68aed8a9553272b 0003a1b2c3d4e5f60718000000016801518068000258fab3bf4996c5d2fdfc33 0ec958d0a5b63624bf3fbdc0fedfa9d94b0941a4060c ticket (130): 00000001d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e1d90c86 474574e0e51e82d8a29938896b0999e827138f8f452f21e044d9809f65a013cf ad8981be94c1354178b3e03dd518c28bcbaab962aa45246e446de7763288aa4a 01e207725a0ae7bc95452fef3743f6083deb10cd23e2881e8d9307fc2f43bce1 a97e control (141): 50514452010000012c008200000001d0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0 e1e2e3e4e5e6e7e1d90c86474574e0e51e82d8a29938896b0999e827138f8f45 2f21e044d9809f65a013cfad8981be94c1354178b3e03dd518c28bcbaab962aa 45246e446de7763288aa4a01e207725a0ae7bc95452fef3743f6083deb10cd23 e2881e8d9307fc2f43bce1a97e response plaintext, padded to 256 (256, SHA-256): a215df14b59d272b506224ed1f6ab5956be2bf189f847dfac4f8649c5f94d99e full response wire (304, SHA-256): 33c081503d5ead4061a30d3f095fc9f226b8c01c3bbffa8fc6f4d9b15087de5c Denis Expires 19 December 2026 [Page 53] Internet-Draft DNSCrypt June 2026 sha256(ticket) (32): fb196d81022c6b480f1340c80987088a85145194c18441928a4ae8e5a153536c resumed shared-key (32): e61f03acb2ee2ef01b952a0c312c60653267d47a2766fcfd804747fdf2fe789f resumed encrypted-query (272, SHA-256): 60323805036492350ee442ee4dcb097597fb586e3f2c8a1f26feb9cdd0409b29 resume query wire (424, SHA-256): 34be2e331b4d7c7e808e968c5efc9f25675a9de9064cb33f7c66950e0e4e6db7 resume response wire, no new ticket (112, SHA-256): 2bf202dd3f33d38854450e70a02bd1a317a23bf6d79c5dae406787c9c5f34f52 15. Normative References [FIPS203] National Institute of Standards and Technology, "Module- Lattice-Based Key-Encapsulation Mechanism Standard", FIPS 203, August 2024, . [RFC1035] Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987, . [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, . [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, . [RFC7766] Dickinson, J., Dickinson, S., Bellis, R., Mankin, A., and D. Wessels, "DNS Transport over TCP - Implementation Requirements", RFC 7766, DOI 10.17487/RFC7766, March 2016, . [RFC5358] Damas, J. and F. Neves, "Preventing Use of Recursive Nameservers in Reflector Attacks", BCP 140, RFC 5358, DOI 10.17487/RFC5358, October 2008, . [RFC9000] Iyengar, J., Ed. and M. Thomson, Ed., "QUIC: A UDP-Based Multiplexed and Secure Transport", RFC 9000, DOI 10.17487/RFC9000, May 2021, . Denis Expires 19 December 2026 [Page 54] Internet-Draft DNSCrypt June 2026 [RFC8439] Nir, Y. and A. Langley, "ChaCha20 and Poly1305 for IETF Protocols", RFC 8439, DOI 10.17487/RFC8439, June 2018, . [RFC7748] Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves for Security", RFC 7748, DOI 10.17487/RFC7748, January 2016, . [RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing Architecture", RFC 4291, DOI 10.17487/RFC4291, February 2006, . [RFC1918] Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. J., and E. Lear, "Address Allocation for Private Internets", BCP 5, RFC 1918, DOI 10.17487/RFC1918, February 1996, . [I-D.connolly-cfrg-xwing-kem] Connolly, D., Schwabe, P., and B. Westerbaan, "X-Wing: general-purpose hybrid post-quantum KEM", Work in Progress, Internet-Draft, draft-connolly-cfrg-xwing-kem- 10, 2 March 2026, . [RFC5869] Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)", RFC 5869, DOI 10.17487/RFC5869, May 2010, . [RFC6891] Damas, J., Graff, M., and P. Vixie, "Extension Mechanisms for DNS (EDNS(0))", STD 75, RFC 6891, DOI 10.17487/RFC6891, April 2013, . Author's Address Frank Denis Individual Contributor Email: fde@00f.net Denis Expires 19 December 2026 [Page 55]