Documentation

The Domain-Keyed Document Stamp (DKDS) is an open protocol for verifying the origin and content of documents. This documentation describes version 1 of the protocol, the procedures for issuing and verifying stamps, and the reference implementation, dkds.js.

Documentation by task#

The documentation is arranged by the task of the reader. The specification is the only normative document; the guides and the security considerations explain it and refer to its sections.

Overview#

DKDS involves three parties and one public infrastructure. An issuer, an organisation that holds a domain name, publishes a public key in the Domain Name System (DNS) and signs the key facts of each document it issues. The signed facts are printed on the document as a QR code, the stamp. A verifier, software used by the recipient of the document, reads the stamp, retrieves the public key from the DNS and checks the signature. The reader, the person who uses the verifier, compares the facts shown by the verifier with those printed on the document.

Issuer
northwind.example
holds the private key
DNS
k2026._dkds.northwind.example
v=DKDS1; k=ed25519; p=6kps…0iw=
Invoice
Verifier
northwind.example, 7 fields
Signature valid
  1. 1The issuer publishes a public key as a TXT record in the DNS of its domain. This is done once, and again whenever the key is replaced.
  2. 2For each document, the issuer signs the key facts with the corresponding private key and prints them, together with the signature, as a QR code on the document.
  3. 3A verifier scans the QR code and reads the facts, the signature and the domain name of the issuer.
  4. 4The verifier retrieves the public key from the DNS of that domain and checks the signature against it.
Figure 1. Issuing and verifying a stamp. Steps 1 and 2 are performed by the issuer, steps 3 and 4 by the verifier.

No party other than the issuer and the DNS is involved. There is no registry of issuers, no certificate authority and no central service; a verifier needs only the stamp and access to the DNS.

Party Function Specification Guide
Issuer Publishes the key record; creates and prints stamps Sections 4 to 7, 10 Issuing documents
DNS Holds the key record at <key_id>._dkds.<domain> Section 7 Issuing documents
Verifier Performs the verification procedure; displays the outcome, the domain and the fields Sections 8 and 9 Building a verifier
Reader Compares the displayed fields with the printed document Section 9.1 Security considerations

Architecture#

The protocol is defined as five layers. Each layer has a single function and depends only on the layers below it in the definition, so that a later version of the protocol can change one layer without affecting the others (specification, section 11).

CarrierSection 3
"DKDS:" || Base45(envelope)QR code, alphanumeric mode, level M, version 27 or lower
EnvelopeSection 4
headerversion, domain, key ID, issued_atpayloadcompressed fieldssignature64 bytes
signed part
PayloadSection 5
countnamevaluenamevalue…
compressed with raw DEFLATE; at most 16,384 bytes uncompressed
SignatureSection 6
Ed25519("DKDS" || signed part)RFC 8032, with canonical encodings and small-order points rejected
Key discoverySection 7
k2026._dkds.northwind.example  TXT
"v=DKDS1; k=ed25519; p=6kpsY+KcUgq+9VB7…"
Figure 2. The five layers of a stamp. The envelope is at most 1,088 bytes; its text form is at most 1,637 characters.

Creating a stamp#

An issuer builds a stamp from the inside out:

  1. The fields, a list of names and values, are encoded and compressed with raw DEFLATE to form the payload.
  2. The header (version, domain, key ID and time of issue) and the payload form the signed part of the envelope.
  3. The signed part, preceded by the ASCII string DKDS, is signed with the issuer's Ed25519 private key. The 64-byte signature completes the envelope.
  4. The envelope is encoded in Base45, preceded by DKDS:, and printed as a QR code.

Verifying a stamp#

A verifier reverses these steps, in the fixed order of the verification procedure (section 8.2):

  1. The QR code is read and the text form decoded into the envelope.
  2. The header is checked. A stamp that fails any check here is rejected without a DNS query.
  3. The key record is retrieved from the lookup name <key_id>._dkds.<domain>.
  4. The signature is verified over DKDS and the signed part.
  5. Only then is the payload decompressed and the fields read.

The order is part of the protocol: it ensures that every verifier reaches the same outcome for the same stamp, and that untrusted data is processed as little as possible before the signature has been checked.

Standards#

Every component of DKDS is an existing published standard.

Component Standard Used in
QR code ISO/IEC 18004 Section 3.3
Base45 RFC 9285 Section 3.2
DEFLATE RFC 1951 Section 5.1
UTF-8 RFC 3629 Section 5.2
Punycode RFC 3492 Section 4.2
Ed25519 RFC 8032 Section 6.3
DNS TXT records RFC 1035 Section 7
Base64 RFC 4648 Section 7.2

Design principles#

The specification follows a small number of principles, which explain most of its rules.

  • One way to do each thing. A protocol version fixes every choice. There are no options, extensions or negotiation within a version, so that two conforming verifiers always agree.
  • One encoding for each value. Base45, Base64 and Ed25519 encodings are accepted only in their canonical form, so that every envelope has exactly one text form.
  • Bounded input. Every length is limited, decompression stops at a fixed size, and no DNS query is made for a stamp that is not well formed.
  • No intermediary. The issuer's own DNS is the only source of keys. Verification requires no account, registry or fee.
  • Statements, not judgements. A verifier reports which domain signed which facts. Whether the facts are true, and whether they match the document, is left to the reader.

Terminology#

Stamp
A QR code printed on a document, containing the issuer's domain, a key ID, the time of issue, the fields and a signature. Section 1
Text form
The string encoded in the QR code: DKDS: followed by the Base45 encoding of the envelope. Section 3.1
Envelope
The binary structure of a stamp: header, payload and signature. Section 4.1
Signed part
The envelope without its signature. Section 4.1
Field
A name and a value, both text, stating one fact of the document. Section 5.1
Payload
The list of fields, compressed with raw DEFLATE. Section 5
Key ID
A short identifier, chosen by the issuer, that distinguishes the keys of one domain. Section 4.3
Lookup name
The DNS name at which the key is published: <key_id>._dkds.<domain>. Section 4.2
Key record
The DNS TXT record that holds the public key, for example v=DKDS1; k=ed25519; p=…. Section 7.2
Revocation
Replacing a key record with one whose p tag is empty, which invalidates every stamp signed with the key. Section 7.4
Outcome
The result of verification: one of valid, malformed, unsupported, key-not-found, key-revoked, invalid-signature and unavailable. Section 8.1
Warning
A notice to the reader, for example about a lookalike domain. Warnings never change the outcome. Section 9.3

Conformance#

An implementation conforms to version 1 when it meets every requirement of the specification.

For a verifier, most requirements are checked mechanically by the test vectors. A verifier passes when, for each of the 145 vectors, it produces the expected outcome, makes the expected DNS queries and, for valid stamps, returns the expected domain, time of issue and fields. The requirements that cannot be checked by comparing outputs, such as the display rules of section 9.1, are listed under requirements not covered by the vectors.

An issuer conforms when every stamp it creates verifies as valid and it follows the issuer requirements of section 10.

Versions#

Component Current version
DKDS protocol 1
dkds.js 0.1.1

The first byte of every envelope identifies the protocol version. A verifier that receives a stamp of a version it does not implement reports unsupported rather than attempting to read it. Later versions change one layer at a time, as described in section 11.