RFC 9498
The GNU Name System
The GNU Name System ๐
Okay bestie, let's get into it! ๐ This is RFC 9498, and it's an Informational doc from the Independent Submission stream, so it isn't an Internet Standard. ๐ธ It was written by M. Schanzenbach (Fraunhofer AISEC), C. Grothoff (Berner Fachhochschule), and B. Fix (GNUnet e.V.), and it's dated November 2023. ISSN: 2070-1721. โจ It doesn't obsolete or update any other RFCs, so it's a solo queen. ๐
Here's the vibe: GNS is a decentralized, censorship-resistant way to resolve names, and it's a privacy-friendly alternative to DNS. ๐ฆ The spec covers the wire format of resource records, the resolution process, the crypto stuff, and the security and privacy considerations, all for implementers. ๐ It wasn't developed inside the IETF and doesn't have IETF consensus, so it's just here to inform people, guide GNS implementers, and keep implementations interoperable, like the existing GNUnet ones. ๐ซถ
Status of This Memo
This document is not an Internet Standards Track specification; it is published for informational purposes. ๐
This is a contribution to the RFC Series, independently of any other RFC stream. The RFC Editor chose to publish it at their discretion and makes no statement about its value for implementation or deployment. ๐ Documents approved by the RFC Editor are not candidates for any level of Internet Standard; see Section 2 of RFC 7841. ๐
Info about the current status, errata, and how to give feedback lives at https://www.rfc-editor.org/info/rfc9498. ๐
Copyright Notice
Copyright (c) 2023 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. Please review these carefully, because they describe your rights and restrictions with respect to this document. ๐
1. Introduction ๐ง
This spec describes the GNU Name System (GNS), a censorship-resistant, privacy-preserving, and decentralized domain name resolution protocol. โจ GNS cryptographically secures the binding of names to arbitrary tokens, so it can double as an alternative to some of today's public key infrastructures. ๐
Per DNS terminology [RFC1035], GNS roughly follows the idea of a local root zone deployment (see [RFC8806]). The difference is that the design encourages alternative roots and doesn't expect every deployment to use the same root zone, or any specific one. ๐ฆ In the GNS reference implementation, users can autonomously and freely delegate control of names to zones through their local configurations. GNS expects each user to be in control of their setup. ๐ By following the guidelines in Section 9.10, users should manage to avoid any confusion about how names get resolved. ๐ซถ
Name resolution and zone dissemination are based on the principle of a petname system, where users can assign local names to zones. ๐ธ GNS has its roots in ideas from the Simple Distributed Security Infrastructure [SDSI], which enables decentralized mapping of secure identifiers to memorable names. ๐ญ One of the first academic descriptions of the cryptographic ideas behind GNS can be found in [GNS]. ๐ฅ
This document defines the normative wire format of resource records, resolution processes, cryptographic routines, and security and privacy considerations for use by implementers. ๐
1.1. Requirements Notation ๐
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. ๐ง Lowercase means it's just regular English, bestie, no cap. โจ
2. Terminology โจ
Apex Label: ๐ธ This label type is used to publish resource records in a zone so they can be resolved without giving a specific label. It's GNS's version of what DNS calls the "zone apex" [RFC4033]. The apex label is written as U+0040 (@, no quotes).
Application: ๐ An application is any component that uses a GNS implementation to resolve names into records and then processes what it gets back.
Blinded Zone Key: ๐ฆ A blinded zone key is derived from a zone key and a label. The zone key and any blinded zone key made from it can't be linked to each other unless you know the exact label used to make the blind.
Extension Label: ๐ง This label type points at the authoritative zone that the record lives in. Its main job is redirection, where the redirection target is defined relative to the authoritative zone of the redirection record (see Section 5.2). The extension label is written as U+002B (+, no quotes).
Label Separator: ๐ Labels in a name are split up by the label separator, U+002E (., no quotes). In GNS, every label separator in a name means delegation to another zone, with two exceptions: zone Top-Level Domains (zTLDs, explained below) and boxed records (see Section 5.3.3).
Label: ๐ A GNS label is a label as defined in [RFC8499]. Labels are UTF-8 strings in Unicode Normalization Form C (NFC) [Unicode-UAX15]. The apex label and the extension label have special jobs in the resolution protocol, which the rest of this document covers. Zone administrators MAY disallow certain labels that could easily be confused with other labels through registration policies (see also Section 9.4). ๐
Name: ๐ A GNS name is a domain name as defined in [RFC8499]. Names are UTF-8 strings [RFC3629] made of an ordered list of labels joined by label separators. Resolution starts from the rightmost label. GNS doesn't put length limits on names or labels. Applications MAY make sure name and label lengths work with DNS and, especially, with Internationalized Domain Names for Applications (IDNA) [RFC5890]. In the spirit of [RFC5895], applications MAY preprocess names and labels to fit DNS or to match specific user expectations, for example by following [Unicode-UTS46]. A GNS name might look exactly like a DNS name, so applications and implementers need to be careful when handling GNS names (see Section 9.10). To avoid mixing up example domains with (reserved) DNS domains, this document uses the suffix .gns.alt in line with [RFC9476]. .gns.alt is also registered in the GANA ".alt Subdomains" registry [GANA]. ๐
Resolver: ๐ฅ In this document, the resolver is the part of a GNS implementation that handles the recursive name resolution logic defined in Section 7.
Resource Record: ๐ A GNS resource record is the information attached to a label in a GNS zone. Each one contains information defined by its resource record type.
Start Zone: ๐ To resolve any GNS name, you first need to figure out an initial Start Zone for it. The Start Zone can be spelled out in the name itself using a zTLD. Otherwise, it's worked out through a local suffix-to-zone mapping (see Section 7.1).
Top-Level Domain (TLD): ๐ The rightmost part of a GNS name is a GNS TLD, and it can be made of one or more labels. Unlike DNS TLDs (defined in [RFC8499]), GNS doesn't expect everyone to share the same global root zone. Instead, apart from zTLDs (see Section 4.1), GNS TLDs usually come from the local resolver's configuration (see Section 7.1), so they might not be globally unique.
Zone: ๐ซถ A GNS zone holds authoritative information (resource records). Each zone is uniquely identified by its zone key. Unlike DNS zones, a GNS zone doesn't need an SOA record under the apex label.
Zone Key: ๐ The zone key is the key that uniquely identifies a zone. It's usually the public key of an asymmetric key pair. However, the established term "public key" is a bit misleading here, because in GNS a zone key may be a shared secret that should not be disclosed to unauthorized parties. ๐
Zone Key Derivation Function: ๐งฎ The zone key derivation function (ZKDF) blinds a zone key using a label.
Zone Publisher: ๐ฎ The zone publisher is the part of a GNS implementation that handles local zone management and publication, as defined in Section 6.
Zone Owner: ๐๏ธ The zone owner holds the secret (usually a private key). That secret, together with a label and a value to sign, lets the owner create zone signatures that can be checked against the matching blinded zone key.
Zone Top-Level Domain (zTLD): ๐ A zTLD is a sequence of GNS labels at the end of a GNS name. It encodes a zone's type and zone key (see Section 4.1). Zone keys are statistically unique, so zTLDs are globally unique too. A zTLD label sequence can only be told apart from an ordinary TLD label sequence by trying to decode the labels into a zone type and zone key. ๐ต๏ธ
Zone Type: ๐ A GNS zone's type decides the cipher system and binary encoding format used for its zone key, blinded zone keys, and cryptographic signatures.
3. Overview ๐ฆ
GNS has the three properties that people usually use to describe a petname system. Let's break them down:
- Global names through the concept of zTLDs: ๐ Zones can be uniquely identified by their zone keys, and those keys are statistically unique. So zTLDs are globally unique mappings to zones. That means GNS domain names with a zTLD suffix are also globally unique. The catch? Names with zTLD suffixes aren't memorable. ๐ญ
- Memorable petnames for zones: ๐งธ Users can set up local, memorable references to zones. These petnames act as zTLD monikers, giving the local operator friendly names for zones. Petnames can also be published as suggestions for other users who are searching for a good label to use for that zone. โจ
- A secure mapping from names to records: ๐ GNS lets zone owners map labels to resource records, or hand off authority over the names in the subdomain a label creates to other zones. Owners can choose to publish this information so others can use it. Mappings are encrypted and signed with keys derived from the relevant label before they go into remote storage. When names are resolved, the recursive resolver verifies the signatures on resource records, delegations included. ๐
In the rest of this document, the "implementer" is the developer building a GNS implementation. That includes the resolver, the zone publisher, and supporting configuration such as Start Zones (see Section 7.1). ๐ ๏ธ
3.1. Names and Zones ๐ท
From the above, it follows that GNS can't support names that are global, secure, and memorable all at once. Instead, names are either global and not memorable, or not globally unique and memorable. ๐ Here's an example of a global name pointing to the record "example" in a zone:
example.000G006K2TJNMD9VTCYRX7BRVV3HAEPS15E6NHDXKPJA1KAJJEG9AFF884
Now imagine a user locally configures the petname pet.gns.alt for the zone that holds the "example" record in the name above. Then example.pet.gns.alt would point to the same record as the globally unique name, but resolution would only work on the local system where the pet.gns.alt petname is configured. ๐
The delegation of petnames and the resolution that follows it are built on ideas from the Simple Distributed Security Infrastructure [SDSI]. In GNS, any user can create and manage any number of zones (see Section 4) as long as their system has a zone publisher implementation. โ๏ธ For each zone, the zone type determines the set of cryptographic operations and the wire formats for encrypted data, public keys, and signatures. The owner can fill a zone with mappings from labels to resource records (see Section 5). A label can also be mapped to a delegation record, which delegates the matching subdomain to another zone. Circular delegations are explicitly allowed, including delegating a subdomain to its immediate parent zone. ๐ To support (legacy) applications and make petnames easier to use, GNS defines auxiliary record types in addition to supporting existing DNS records. ๐
3.2. Publishing Binding Information ๐ฎโจ
okay so zone contents get encrypted AND signed before they're published in remote key-value storage (see Section 6) ๐, and Figure 1 shows the whole vibe ๐ฆ. the big trick is that the zone's unique identity stays hidden from the network thanks to key blinding ๐ซฃ. key blinding lets you create signatures for zone contents using a blinded public/private key pair ๐ . the blinding comes from a deterministic key derivation using the original zone key and its corresponding private key ๐ง , and the blinding factors are derived from record label values. so the zone owner can derive blinded private keys for each record set published under a label, and a resolver can derive the matching blinded public keys ๐. ngl that's so clean.
GNS implementations are expected to use decentralized remote storage entities, like distributed hash tables (DHTs) ๐. this keeps things available across the network without needing dedicated infrastructure โจ. the spec for that kind of distributed storage is out of scope for this doc ๐ โโ๏ธ, but possible existing implementations include those based on [RFC7363], [Kademlia], or [R5N] ๐.
Host A | Remote | Host B
| Storage |
| |
| +---------+ |
| / /| |
Publish | +---------+ | | Publish
+-----------+ Records | | | | | Records +-----------+
| Zone |----------|->| Record | |<-|----------| Zone |
| Publisher | | | Storage | | | | Publisher |
+-----------+ | | |/ | +-----------+
A | +---------+ | A
| | | |
+---------+ | | +---------+
/ | /| | | / | /|
+---------+ | | | +---------+ |
| | | | | | | |
| Local | | | | | Local | |
| Zones | | | | | Zones | |
| |/ | | | |/
+---------+ | | +---------+
Figure 1: An Example Diagram of Two Hosts Publishing GNS Zones ๐
a zone publisher implementation SHOULD be provided as part of a GNS implementation so users can create and manage zones ๐. if that functionality isn't implemented, names can still be resolved if zone keys for the initial step in the name resolution have been configured (see Section 7) ๐ง, or if the names end with a zTLD suffix ๐ซถ.
3.3. Resolving Names ๐
so apps use the resolver to look up GNS names ๐โโ๏ธ. starting from a configurable Start Zone, names get resolved by following zone delegations recursively ๐บ๏ธ (see Figure 2). for each label in a name, the recursive GNS resolver fetches the respective record set from the storage layer (see Section 7) ๐ฆ. without knowledge of the label values and the zone keys, the different derived keys are unlinkable to both the original zone key and each other ๐งฉ. this prevents zone enumeration (except via expensive online brute-force attacks) ๐. to confirm the affiliation of a query, or its encrypted record set, with a specific zone, you need both the zone key and the label, and neither one is disclosed to remote storage by the protocol ๐คซ. at the same time, the blinded zone key and the digital signatures attached to each encrypted record set let resolvers and oblivious remote storage verify integrity without learning anything about the originating zone or the record sets ๐ฆ.
Local Host | Remote
| Storage
|
| +---------+
| / /|
| +---------+ |
+-----------+ Name +----------+ Recursive | | | |
| | Lookup | | Resolution | | Record | |
|Application|--------->| Resolver |-------------|->| Storage | |
| |<---------| |<------------|--| |/
+-----------+ Results +----------+ Intermediate| +---------+
A Results |
| |
+---------+ |
/ | /| |
+---------+ | |
| | | |
| Start | | |
| Zones | | |
| |/ |
+---------+ |
Figure 2: High-Level View of the GNS Resolution Process ๐งญ
4. Zones ๐
okay zones are the main character here ๐. a zone in GNS is uniquely identified by its zone type (ztype) and zone key ๐. each zone can be referenced by its zTLD (see Section 4.1 โจ), which is a string that encodes the zone type and zone key. the ztype is a unique 32-bit number that corresponds to a resource record type number identifying a delegation record type in the GANA "GNS Record Types" registry [GANA] ๐. it's the unique identifier for the set of cryptographic functions of the zone and the format of the delegation record type ๐ง. any ztype registration MUST define the following set of cryptographic functions:
KeyGen() -> d, zkey A function for generating a new private key d and the corresponding public zone key zkey. ๐๏ธ
ZKDF(zkey, label) -> zkey' A ZKDF that blinds a zone key zkey using a label. zkey and zkey' must be unlinkable. furthermore, blinding zkey with different values for the label must result in different, unlinkable zkey' values. ๐
S-Encrypt(zkey, label, expiration, plaintext) -> ciphertext A symmetric encryption function that encrypts the plaintext to derive ciphertext based on key material derived from the zone key zkey, a label, and an expiration timestamp. to leverage performance-enhancing caching features of certain underlying storage entities (in particular, DHTs), a deterministic encryption scheme is recommended. ๐
S-Decrypt(zkey, label, expiration, ciphertext) -> plaintext A symmetric decryption function that decrypts the ciphertext into plaintext based on key material derived from the zone key, a label, and an expiration timestamp. ๐
Sign(d, message) -> signature A function for signing a message using the private key d, yielding an unforgeable cryptographic signature. to leverage performance-enhancing caching features of certain underlying storage entities (in particular, DHTs), a deterministic signature scheme is recommended. โ๏ธ
Verify(zkey, message, signature) -> boolean A function for verifying that the signature was created using the private key d corresponding to the zone key zkey, where d,zkey := KeyGen(). the function returns a boolean value of "TRUE" if the signature is valid and "FALSE" otherwise. โ
SignDerived(d, label, message) -> signature A function for signing a message (typically encrypted record data) that can be verified using the derived zone key zkey' := ZKDF(zkey, label). to leverage performance-enhancing caching features of certain underlying storage entities (in particular, DHTs), a deterministic signature scheme is recommended. ๐๏ธ
VerifyDerived(zkey', message, signature) -> boolean A function for verifying the signature using the derived zone key zkey' := ZKDF(zkey, label). the function returns a boolean value of "TRUE" if the signature is valid and "FALSE" otherwise. depending on the signature scheme used, this function can be identical to the Verify() function. ๐ง
the cryptographic functions of the default ztypes are specified with their corresponding delegation records, as discussed in Section 5.1 ๐. to support cryptographic agility, additional ztypes MAY be defined in the future that replace or update the default ztypes defined in this document ๐. all ztypes MUST be registered as dedicated zone delegation record types in the GANA "GNS Record Types" registry (see [GANA]) ๐. when defining new record types, the cryptographic security considerations of this document (in particular, Section 9.3) apply ๐ก๏ธ.
4.1. Zone Top-Level Domain (zTLD) ๐
a zTLD is a string that encodes the zone type and zone key into a domain name suffix ๐ท๏ธ. it's used as a globally unique reference to a zone during name resolution. it's created by encoding a binary concatenation of the zone type and zone key (see Figure 3) ๐งฉ. the encoding is a variation of Crockford Base32 encoding [CrockfordB32] called Base32GNS. the encoding and decoding symbols for Base32GNS, including this variation, are defined in Table 4, found in Appendix C ๐. the functions for encoding and decoding based on Table 4 are called Base32GNS-Encode and Base32GNS-Decode, respectively.
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| ZONE TYPE | ZONE KEY /
+-----+-----+-----+-----+ /
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 3: The Binary Representation of the zTLD ๐
the ZONE TYPE MUST be encoded in network byte order ๐ข. the format of the ZONE KEY depends entirely on the ZONE TYPE ๐ค.
so a zTLD is encoded and decoded like this ๐:
zTLD := Base32GNS-Encode(ztype||zkey)
ztype||zkey := Base32GNS-Decode(zTLD)
where "||" is the concatenation operator.
the zTLD can be used "as is" as a rightmost label in a GNS name โจ. if an application wants to make sure the name is DNS compatible, it MAY also represent the zTLD as follows ๐: if the zTLD is less than or equal to 63 characters, it can be used as a zTLD as is. if the zTLD is longer than 63 characters, it gets divided into smaller labels separated by the label separator. here, the most significant bytes of the "ztype||zkey" concatenation must be contained in the rightmost label of the resulting string, and the least significant bytes in the leftmost label. this lets the resolver figure out the ztype and zTLD length from the rightmost label, and then work out how many labels the zTLD should span ๐ง . a GNS implementation MUST support the division of zTLDs in DNS-compatible label lengths ๐ซถ. for example, assuming a zTLD of 130 characters, the division is as follows:
zTLD[126..129].zTLD[63..125].zTLD[0..62]
4.2. Zone Revocation โจ
Okay bestie, revoking a zone key is a whole production ๐ A signed revocation message MUST be published, and it MUST be signed with the zone's private key ๐ The message gets broadcast to the network. The broadcast mechanism itself is out of scope for this document, but [GNUnet] implements one that does efficient flooding in a distributed network ๐ Revocation messages could also be distributed through a distributed ledger or a trusted central server instead ๐ง To stop flooding attacks, the revocation message MUST contain a proof of work (PoW) ๐ก๏ธ The revocation message, PoW included, MAY be calculated ahead of time so it can be timely โฐ
For everything below, "Argon2id" is the password-based key derivation function from [RFC9106] ๐ธ For the PoW calculations, the algorithm gets set up with these parameters:
S: The salt. Fixed 16-byte string:"GnsRevocationPow"t: Number of iterations: 3m: Memory size in KiB: 1024T: Output length of hash in bytes: 64p: Parallelization parameter: 1v: Algorithm version:0x13y: Algorithm type (Argon2id): 2X: UnusedK: Unused
Figure 4 shows the format of the data "P" that the PoW gets calculated on ๐ฆ
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| POW |
+-----------------------------------------------+
| TIMESTAMP |
+-----------------------------------------------+
| ZONE TYPE | ZONE KEY /
+-----+-----+-----+-----+ /
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 4: The Format of the PoW Data
POW: A 64-bit value that is a solution to the PoW. In network byte order.TIMESTAMP: Denotes the absolute 64-bit date when the revocation was computed. In microseconds since midnight (0 hour), January 1, 1970 UTC in network byte order.ZONE TYPE: The 32-bit zone type in network byte order.ZONE KEY: The 256-bit public keyzkeyof the zone that is being revoked. The wire format of this value is defined by theZONE TYPE.
Usually, PoW schemes require that one POW value be found, such that a specific number of leading zeroes are found in the hash result. This number is then referred to as the difficulty of the PoW. To reduce the variance in the time it takes to calculate the PoW, a valid GNS revocation requires that a number of different PoWs (Z, as defined below) must be found that on average have at least D leading zeroes ๐งฎ
Given an average difficulty of D, the proofs have an expiration time of EPOCH. Applications MAY calculate proofs with a difficulty that is higher than D by providing POW values where there are (on average) more than D bits of leading zeroes. With each additional bit of difficulty, the lifetime of the proof is prolonged by another EPOCH. So by calculating a harder PoW, the zone owner can increase the lifetime of the proof, and therefore the persistence of the revocation message, on demand ๐ช
The parameters are defined as follows:
Z: The number of PoWs that are required. Its value is fixed at 32.D: The lower limit of the average difficulty. Its value is fixed at 22.EPOCH: A single epoch. Its value is fixed at 365 days in microseconds.
The revocation message wire format is illustrated in Figure 5 ๐
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| TIMESTAMP |
+-----+-----+-----+-----+-----+-----+-----+-----+
| TTL |
+-----+-----+-----+-----+-----+-----+-----+-----+
| POW_0 |
+-----+-----+-----+-----+-----+-----+-----+-----+
| ... |
+-----+-----+-----+-----+-----+-----+-----+-----+
| POW_(Z-1) |
+-----------------------------------------------+
| ZONE TYPE | ZONE KEY /
+-----+-----+-----+-----+ /
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
/ SIGNATURE /
/ /
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 5: The Revocation Message Wire Format
TIMESTAMP: Denotes the absolute 64-bit date when the revocation was computed. In microseconds since midnight (0 hour), January 1, 1970 UTC in network byte order. This is the same value as the timestamp used in the individual PoW calculations.TTL: Denotes the relative 64-bit time to live of the record in microseconds in network byte order. The field SHOULD be set toEPOCH * 1.1. Given an average number of leading zeroes D', then the field value MAY be increased up to(D'-D+1) * EPOCH * 1.1. Validators MAY reject messages with lower or higher values when received. โณPOW_i: The values calculated as part of the PoW, in network byte order. Each POW_i MUST be unique in the set of POW values. To make uniqueness quick to verify, the POW values MUST be given in strictly monotonically increasing order in the message. ๐ขZONE TYPE: The 32-bit zone type corresponding to the zone key in network byte order.ZONE KEY: The public keyzkeyof the zone that is being revoked and the key to be used to verifySIGNATURE.SIGNATURE: A signature over a timestamp and thezkeyof the zone that is revoked, corresponding to the key used in the PoW. The signature is created using theSign()function of the cryptosystem of the zone and the private key (see Section 4). โ๏ธ
The signature in the revocation message covers a 32-bit header prefixed to the TIMESTAMP, ZONE TYPE, and ZONE KEY fields. The header includes the key length and signature purpose. The wire format is illustrated in Figure 6 ๐ง
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIZE | PURPOSE (0x03) |
+-----+-----+-----+-----+-----+-----+-----+-----+
| TIMESTAMP |
+-----+-----+-----+-----+-----+-----+-----+-----+
| ZONE TYPE | ZONE KEY /
+-----+-----+-----+-----+ /
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 6: The Wire Format of the Revocation Data for Signing
SIZE: A 32-bit value containing the length of the signed data in bytes in network byte order.PURPOSE: A 32-bit signature purpose flag. The value of this field MUST be 3. The value is encoded in network byte order. It defines the context in which the signature is created so that it cannot be reused in other parts of the protocol that might include possible future extensions. The value of this field corresponds to an entry in the GANA "GNUnet Signature Purposes" registry [GANA]. ๐TIMESTAMP: Field as defined in the revocation message above.ZONE TYPE: Field as defined in the revocation message above.ZONE KEY: Field as defined in the revocation message above.
In order to validate a revocation, the following steps MUST be taken:
- The signature MUST be verified against the zone key.
- The set of POW values MUST NOT contain duplicates; this MUST be checked by verifying that the values are strictly monotonically increasing.
- The average number of leading zeroes D' resulting from the provided POW values MUST be greater than or equal to D. Implementers MUST NOT use an integer data type to calculate or represent D'.
The TTL field in the revocation message is informational, so don't let it fool you ๐ A revocation MAY be discarded without checking the POW values or the signature if the TTL (in combination with TIMESTAMP) indicates that the revocation has already expired. The actual validity period of the revocation MUST be determined by examining the leading zeroes in the POW values.
The validity period of the revocation is calculated as (D'-D+1) * EPOCH * 1.1. The EPOCH gets stretched by 10% to deal with poorly synchronized clocks โฐ The validity period gets added on top of the TIMESTAMP to give the expiration date. If the current time is after the expiration date, the revocation is considered stale ๐
Verified revocations MUST be stored locally. The implementation MAY discard stale revocations and evict them from the local store at any time ๐๏ธ
It is important that implementations broadcast received revocations if they are valid and not stale ๐ฃ Should the calculated validity period differ from the TTL field value, the calculated value MUST be used as the TTL field value when forwarding the revocation message. Systems might disagree on the current time, so implementations MAY use stale but otherwise valid revocations, but SHOULD NOT broadcast them. Forwarded stale revocations MAY be discarded by the receiver. ๐ซถ
Any locally stored revocation MUST be considered during delegation record processing (see Section 7.3.4) ๐
5. Resource Records โจ
okay bestie, so a GNS implementation SHOULD provide a mechanism for creating and managing local zones ๐ plus a persistence mechanism (like a local database ๐๏ธ) for resource records. making a new local zone is giving pick a zone type, then make a zone key pair ๐. if this mechanism isn't implemented, no zones can be published in storage (see Section 6) and name resolution is limited to non-local Start Zones (see Section 7.1) ๐.
a GNS resource record holds the data of one specific record in a zone ๐ฆ. the format is shown in Figure 7:
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| EXPIRATION |
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIZE | FLAGS | TYPE |
+-----+-----+-----+-----+-----+-----+-----+-----+
| DATA /
/ /
/ /
Figure 7: The Resource Record Wire Format
here's the breakdown, it's lowkey so clean ๐ง:
EXPIRATION: the absolute 64-bit expiration date of the record ๐๏ธ. It's microseconds since midnight (0 hour), January 1, 1970 UTC, in network byte order.SIZE: the 16-bit size of theDATAfield in bytes, in network byte order.FLAGS: a 16-bit field for special properties of the resource record. The semantics of the different bits are defined below.TYPE: the 32-bit resource record type, in network byte order. This can be one of the GNS resource records defined in Section 5, a DNS record type as defined in [RFC1035], or any of the complementary standardized DNS resource record types. Values below 2^16 are reserved for 16-bit DNS resource record types allocated by IANA [RFC6895]. Values above 2^16 are allocated by the GANA "GNS Record Types" registry [GANA].DATA: the variable-length resource record data payload ๐ฆ. Its content is defined by the respective type of the resource record.
the FLAGS field is how you tell the world something special is going on ๐ฉ. An application creating resource records MUST set all bits in FLAGS to 0, unless it specifically understands and wants to set the respective flag. more flags can be defined in future protocol versions, so if an application or implementation runs into a flag it doesn't recognize, the flag MUST be ignored ๐. however, all implementations MUST understand the SHADOW and CRITICAL flags defined below. any combination of the flags below is valid โจ. Figure 8 shows how the flags are laid out in the 16-bit FLAGS field:
0 13 14 15
+--------...+-------------+-------+---------+
| Reserved |SUPPLEMENTAL |SHADOW |CRITICAL |
+--------...+-------------+-------+---------+
Figure 8: The Resource Record Flag Wire Format
CRITICAL: when this flag is set, it means processing is critical ๐จ. Implementations that don't support the record type, or are otherwise unable to process the record, MUST abort resolution upon encountering the record in the resolution process. no vibes-based resolving here ๐ .SHADOW: when this flag is set, this record MUST be ignored by resolvers unless all (other) records of the same record type have expired ๐ป. It lets zone publishers prep good performance when records change, by putting future values of records into storage. that way the future values can propagate and get cached before the transition goes live ๐ธ.SUPPLEMENTAL: this is a supplemental record ๐. It's provided in addition to the other records. It's not explicitly managed alongside the other records under the respective name, but it might be useful for the application.
5.1. Zone Delegation Records ๐
okay so this section defines the initial set of zone delegation record types ๐. Any implementation SHOULD support all zone types defined here, and MAY support any number of additional delegation records defined in the GANA "GNS Record Types" registry (see [GANA]). not supporting some zone types will result in resolution failures if that zone type shows up, which is valid if some zone delegation record types have been determined to be cryptographically insecure ๐. Zone delegation records MUST NOT be stored or published under the apex label ๐
. a zone delegation record type value is the same as the respective ztype value. the ztype defines the cryptographic primitives for the zone being delegated to, and the zone delegation record payload contains the public key of the zone to delegate to ๐. a zone delegation record MUST have the CRITICAL flag set and MUST be the only non-supplemental record under a label. There MAY be inactive records of the same type with the SHADOW flag set, to make smooth key rollovers easier ๐ฆ.
in the following, "||" is the concatenation operator of two byte strings ๐งฉ. The algorithm specification uses character strings like GNS labels or constant values. when they're used in concatenations or as input to functions, the zero terminator of the character strings MUST NOT be included ๐.
5.1.1. PKEY ๐
in GNS, a delegation of a label to a zone of type "PKEY" is represented through a PKEY record ๐. The PKEY DATA entry wire format is shown in Figure 9:
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| PUBLIC KEY |
| |
| |
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 9: The PKEY Wire Format
PUBLIC KEY: a 256-bit Ed25519 public key ๐๏ธ.
for PKEY zones, the zone key material is derived using the curve parameters of the twisted Edwards representation of Curve25519 [RFC7748] (the reasoning behind choosing this curve is in Section 9.3) with the ECDSA scheme [RFC6979] ๐ง . the cryptographic primitives for PKEY zones use this naming convention:
d: a 256-bit Ed25519 private key (clamped private scalar).zkey: the Ed25519 public zone key corresponding tod.p: the prime of edwards25519 as defined in [RFC7748], i.e.,2^255 - 19.G: the group generator(X(P),Y(P)), withX(P),Y(P)of edwards25519 as defined in [RFC7748].L: the order of the prime-order subgroup of edwards25519 as defined in [RFC7748].KeyGen(): the generation of the private scalardand the curve pointzkey := d*G(whereGis the group generator of the elliptic curve), as defined in Section 2.2 of [RFC6979], represents theKeyGen()function โจ.
the zone type and zone key of a PKEY are 4 + 32 bytes long ๐. That means a zTLD will always fit into a single label and doesn't need any further conversion ๐. given a label, the output zkey' of the ZKDF(zkey, label) function is calculated like this for PKEY zones:
ZKDF(zkey, label):
PRK_h := HKDF-Extract("key-derivation", zkey)
h := HKDF-Expand(PRK_h, label || "gns", 512 / 8)
zkey' := (h mod L) * zkey
return zkey'
the PKEY cryptosystem uses an HMAC-based key derivation function (HKDF) as defined in [RFC5869], with SHA-512 [RFC6234] for the extraction phase and SHA-256 [RFC6234] for the expansion phase ๐ค. PRK_h is key material retrieved using an HKDF that uses the string "key-derivation" as the salt and the zone key as the initial keying material. h is the 512-bit HKDF expansion result and must be interpreted in network byte order. the expansion information input is a concatenation of the label and the string "gns". the multiplication of zkey with h in ZKDF() is a point multiplication, while the multiplication of d with h in SignDerived() below is a scalar multiplication. it's a lot, but it's so worth it ๐
.
the Sign() and Verify() functions for PKEY zones are implemented using 512-bit ECDSA deterministic signatures as specified in [RFC6979] โ๏ธ. the same functions can be used for derived keys:
SignDerived(d, label, message):
zkey := d * G
PRK_h := HKDF-Extract("key-derivation", zkey)
h := HKDF-Expand(PRK_h, label || "gns", 512 / 8)
d' := (h * d) mod L
return Sign(d', message)
a signature is valid for the derived public key zkey' := ZKDF(zkey, label) if the following holds:
VerifyDerived(zkey', message, signature):
return Verify(zkey', message, signature)
the S-Encrypt() and S-Decrypt() functions use AES in counter mode as defined in [MODES] (CTR-AES256) ๐:
S-Encrypt(zkey, label, expiration, plaintext):
PRK_k := HKDF-Extract("gns-aes-ctx-key", zkey)
PRK_n := HKDF-Extract("gns-aes-ctx-iv", zkey)
K := HKDF-Expand(PRK_k, label, 256 / 8)
NONCE := HKDF-Expand(PRK_n, label, 32 / 8)
BLOCK_COUNTER := 0x0000000000000001
IV := NONCE || expiration || BLOCK_COUNTER
return CTR-AES256(K, IV, plaintext)
S-Decrypt(zkey, label, expiration, ciphertext):
PRK_k := HKDF-Extract("gns-aes-ctx-key", zkey)
PRK_n := HKDF-Extract("gns-aes-ctx-iv", zkey)
K := HKDF-Expand(PRK_k, label, 256 / 8)
NONCE := HKDF-Expand(PRK_n, label, 32 / 8)
BLOCK_COUNTER := 0x0000000000000001
IV := NONCE || expiration || BLOCK_COUNTER
return CTR-AES256(K, IV, ciphertext)
the key K and the counter Initialization Vector (IV) are derived from the record label and the zone key zkey, using an HKDF as defined in [RFC5869] ๐ง. SHA-512 [RFC6234] is used for the extraction phase and SHA-256 [RFC6234] for the expansion phase. the output keying material is 32 bytes (256 bits) for the symmetric key and 4 bytes (32 bits) for the NONCE. the symmetric key K is a 256-bit AES key [RFC3826] ๐.
the nonce is combined with a 64-bit IV and a 32-bit block counter, as defined in [RFC3686] ๐งฉ. the block counter begins with a value of 1, and it's incremented to generate subsequent portions of the key stream. the block counter is a 32-bit integer value in network byte order. Figure 10 shows the format of the counter IV used by the S-Encrypt() and S-Decrypt() functions:
0 8 16 24 32
+-----+-----+-----+-----+
| NONCE |
+-----+-----+-----+-----+
| EXPIRATION |
| |
+-----+-----+-----+-----+
| BLOCK COUNTER |
+-----+-----+-----+-----+
Figure 10: Structure of the Counter IV as Used in S-Encrypt() and S-Decrypt()
5.1.2. EDKEY ๐โจ
okay bestie, so in GNS, a delegation of a label to an "EDKEY" zone gets represented through an EDKEY record ๐ the EDKEY DATA entry wire format is in Figure 11, check it out ๐ฆ
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| PUBLIC KEY |
| |
| |
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 11: The EDKEY DATA Wire Format
the PUBLIC KEY is a 256-bit EdDSA zone key ๐๐
so for EDKEY zones, the zone key material is derived using the curve parameters of the twisted Edwards representation of Curve25519 [RFC7748] (a.k.a. Ed25519) with the Ed25519 scheme [ed25519] as specified in [RFC8032] ๐ the naming convention for the crypto primitives goes like this:
d: a 256-bit EdDSA private key ๐๏ธa: an integer derived fromdusing the SHA-512 hash function as defined in [RFC8032] ๐งฎzkey: the EdDSA public key corresponding tod. it's defined as the curve pointa*GwhereGis the group generator of the elliptic curve as defined in [RFC8032] โจp: the prime of edwards25519 as defined in [RFC8032], i.e.,2^255 - 19๐G: the group generator(X(P),Y(P)), withX(P),Y(P)of edwards25519 as defined in [RFC8032] ๐L: the order of the prime-order subgroup of edwards25519 as defined in [RFC8032] ๐KeyGen(): the generation of the private keydand the associated public keyzkey := a*G(whereGis the group generator of the elliptic curve andais an integer derived fromdusing the SHA-512 hash function) as defined in Section 5.1.5 of [RFC8032] represents theKeyGen()function ๐ซถ
the zone type and zone key of an EDKEY are 4 + 32 bytes in length ๐ง which means a zTLD will always fit into a single label and doesn't need any further conversion. no cap, that's so clean ๐
the "EDKEY" ZKDF instantiation is based on [Tor224] ๐ธ same as above for KeyGen(), a is calculated from d using the SHA-512 hash function as defined in Section 5.1.5 of [RFC8032]. given a label, the ZKDF output gets calculated like this:
ZKDF(zkey, label):
/* Calculate the blinding factor */
PRK_h := HKDF-Extract("key-derivation", zkey)
h := HKDF-Expand(PRK_h, label || "gns", 512 / 8)
/* Ensure that h == h mod L */
h := h mod L
zkey' := h * zkey
return zkey'
Implementers SHOULD employ a constant-time scalar multiplication for the constructions above to protect against timing attacks ๐ otherwise, timing attacks could leak private key material if an attacker can predict when a system starts the publication process ๐
the EDKEY cryptosystem uses an HKDF as defined in [RFC5869], with SHA-512 [RFC6234] for the extraction phase and HMAC-SHA-256 [RFC6234] for the expansion phase ๐ฆ PRK_h is key material retrieved using an HKDF that uses the string "key-derivation" as the salt and the zone key as the initial keying material. the blinding factor h is the 512-bit HKDF expansion result. the expansion information input is a concatenation of the label and the string "gns". the result of the HKDF must be clamped and interpreted in network byte order. a is the 256-bit integer corresponding to the 256-bit private key d. and the multiplication of zkey with h is a point multiplication ๐ฅ
The Sign(d, message) and Verify(zkey, message, signature) procedures MUST be implemented as defined in [RFC8032]. ๐จ
signatures for EDKEY zones use a derived private scalar d', and this is not compliant with [RFC8032] ๐ since the private key that corresponds to the derived private scalar isn't known, it's not possible to deterministically derive the signature part R according to [RFC8032]. instead, signatures MUST be generated as follows for any given message and private zone key: a nonce is calculated from the highest 32 bytes of the expansion of the private key d and the blinding factor h. the nonce is then hashed with the message to r. this way, the full derivation path is included in the calculation of the R value of the signature, so it's never reused for two different derivation paths or messages ๐คฏ๐
SignDerived(d, label, message):
/* Key expansion */
dh := SHA-512(d)
/* EdDSA clamping */
a := dh[0..31]
a[0] := a[0] & 248
a[31] := a[31] & 127
a[31] := a[31] | 64
/* Calculate zkey corresponding to d */
zkey := a * G
/* Calculate blinding factor */
PRK_h := HKDF-Extract("key-derivation", zkey)
h := HKDF-Expand(PRK_h, label || "gns", 512 / 8)
/* Ensure that h == h mod L */
h := h mod L
d' := (h * a) mod L
nonce := SHA-256(dh[32..63] || h)
r := SHA-512(nonce || message)
R := r * G
S := r + SHA-512(R || zkey' || message) * d' mod L
return (R,S)
a signature (R,S) is valid for the derived public key zkey' := ZKDF(zkey, label) if the following holds:
VerifyDerived(zkey', message, signature):
(R,S) := signature
return S * G == R + SHA-512(R, zkey', message) * zkey'
the S-Encrypt() and S-Decrypt() functions use XSalsa20 as defined in [XSalsa20], and they use the XSalsa20-Poly1305 encryption function ๐ง
S-Encrypt(zkey, label, expiration, plaintext):
PRK_k := HKDF-Extract("gns-xsalsa-ctx-key", zkey)
PRK_n := HKDF-Extract("gns-xsalsa-ctx-iv", zkey)
K := HKDF-Expand(PRK_k, label, 256 / 8)
NONCE := HKDF-Expand(PRK_n, label, 128 / 8)
IV := NONCE || expiration
return XSalsa20-Poly1305(K, IV, plaintext)
S-Decrypt(zkey, label, expiration, ciphertext):
PRK_k := HKDF-Extract("gns-xsalsa-ctx-key", zkey)
PRK_n := HKDF-Extract("gns-xsalsa-ctx-iv", zkey)
K := HKDF-Expand(PRK_k, label, 256 / 8)
NONCE := HKDF-Expand(PRK_n, label, 128 / 8)
IV := NONCE || expiration
return XSalsa20-Poly1305(K, IV, ciphertext)
the XSalsa20-Poly1305 encryption output is the encrypted ciphertext followed by the 128-bit authentication tag ๐ซง so the length of the encrypted data equals the length of the data plus the 16 bytes of the auth tag โจ
the key K and counter IV are derived from the record label and the zone key zkey using an HKDF as defined in [RFC5869]. SHA-512 [RFC6234] is used for extraction and SHA-256 [RFC6234] for expansion. the output keying material is 32 bytes (256 bits) for the symmetric key and 16 bytes (128 bits) for the NONCE. the symmetric key K is a 256-bit XSalsa20 key [XSalsa20]. no additional authenticated data (AAD) is used ๐ท
the nonce gets combined with an 8-byte IV. the IV is the expiration time of the resource record block in network byte order. the resulting counter (IV) wire format is in Figure 12 ๐
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| NONCE |
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
| EXPIRATION |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 12: The Counter Block Initialization Vector
5.2. Redirection Records ๐ฆ
okay so redirection records are used to redirect resolution ๐ง any implementation SHOULD support all redirection record types defined here, and it MAY support any number of additional redirection records defined in the GANA "GNS Record Types" registry [GANA] ๐ redirection records MUST have the CRITICAL flag set. not supporting some record types can result in resolution failures ๐ญ this can be a valid choice if some redirection record types have been determined to be insecure, or if an application has reasons to not support redirection to DNS for reasons such as complexity or security. and redirection records MUST NOT be stored or published under the apex label ๐
5.2.1. REDIRECT ๐ธ
a REDIRECT record is the GNS equivalent of a CNAME record in DNS โจ a REDIRECT record MUST be the only non-supplemental record under a label. there MAY be inactive records of the same type that have the SHADOW flag set, in order to facilitate smooth changes of redirection targets. no other records are allowed. details on processing this record are in Section 7.3.1, so go check that out ๐ a REDIRECT DATA entry is illustrated in Figure 13:
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| REDIRECT NAME |
/ /
/ /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 13: The REDIRECT DATA Wire Format
REDIRECT NAME: the name to continue with. this value can be a regular name or a relative name. relative GNS names are indicated by an extension label (U+002B ("+")) as the rightmost label. the string is UTF-8 encoded and zero terminated ๐ซถ
5.2.2. GNS2DNS ๐
a GNS2DNS record delegates resolution to DNS ๐ the resource record contains a DNS name for the resolver to continue with in DNS, followed by a DNS server. both names are in the format defined in [RFC1034] for DNS names. there MAY be multiple GNS2DNS records under a label. there MAY also be DNSSEC DS records, or any other records used to secure the connection with the DNS servers, under the same label. there MAY be inactive records of the same type or types that have the SHADOW flag set, in order to facilitate smooth changes of redirection targets. no other non-supplemental record types are allowed in the same record set. a GNS2DNS DATA entry is illustrated in Figure 14 ๐ง
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| NAME |
/ /
/ /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
| DNS SERVER NAME |
/ /
/ /
| |
+-----------------------------------------------+
Figure 14: The GNS2DNS DATA Wire Format
NAME: the name to continue with in DNS. the value is UTF-8 encoded and zero terminated ๐
DNS SERVER NAME: the DNS server to use. this value can be an IPv4 address in dotted-decimal form, an IPv6 address in colon-hexadecimal form, or a DNS name. it can also be a relative GNS name ending with a "+" as the rightmost label. the implementation MUST check the string syntactically for an IP address in the respective notation before checking for a relative GNS name. if all three checks fail, the name MUST be treated as a DNS name. the value is UTF-8 encoded and zero terminated ๐ธ
NOTE: If an application uses DNS names obtained from GNS2DNS records in a DNS request, they MUST first be converted to an IDNA-compliant representation [RFC5890]. โ ๏ธ๐ซถ
5.3. Auxiliary Records ๐
okay last bit of this part: this section defines the initial set of auxiliary GNS record types ๐ฆ any implementation SHOULD be able to process the specified record types according to Section 7.3. ๐โจ
5.3.1. LEHO ๐
Okay so LEHO stands for LEgacy HOstname, and it's basically a little hint for old-school hostnames ๐ . Apps can use GNS to look up IPv4 or IPv6 addresses of internet services, right? But connecting sometimes needs more than just an IP and port. It also needs the canonical DNS name of the service sent over the transport protocol ๐ฆ. So in GNS, LEHO records hand apps the DNS name they need to connect. The big use case is HTTP virtual hosting and TLS Server Name Indication [RFC6066], where you have to supply a DNS name in the HTTP "Host"-header and the TLS handshake ๐ธ. Using a GNS name there might not work, because it might not be globally unique ๐. And even if uniqueness isn't an issue, the legacy service might not even know GNS exists ๐.
A LEHO resource record is expected to show up together with A or AAAA resource records that carry IPv4 or IPv6 addresses ๐ง. Here's what a LEHO DATA entry looks like in Figure 15 โจ:
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| LEGACY HOSTNAME |
/ /
/ /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 15: The LEHO DATA Wire Format
LEGACY HOSTNAME: a UTF-8 string (not zero terminated) that holds the legacy hostname ๐.
NOTE: If an application uses a LEHO value in an HTTP request header (like a "Host"-header), it MUST be converted to an IDNA-compliant representation [RFC5890] ๐ฅ.
5.3.2. NICK ๐
Nickname records are how zone admins publish a label that their zone would like to be called ๐. It's a suggestion for other zones about which label to use when they create a delegation record (Section 5.1) containing this zone key ๐. This record SHOULD only be stored locally under the apex label "@", but it MAY be returned with record sets under any label as a supplemental record ๐ซถ. Section 7.3.5 explains how a resolver must process supplemental and non-supplemental NICK records โจ. Here's the NICK DATA entry in Figure 16:
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| NICKNAME |
/ /
/ /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 16: The NICK DATA Wire Format
NICKNAME: a UTF-8 string (not zero terminated) for the zone's preferred label ๐ฆ. This string MUST be a valid GNS label ๐ .
5.3.3. BOX ๐
GNS lookups are expected to return all the useful info in one record set, bestie ๐. This avoids extra lookups and cryptographically ties together stuff that belongs together, so an adversarial storage entity can't hand you partial answers that leave out something critical for security ๐ญ๐.
This whole strategy clashes with the special labels DNS uses for SRV and TLSA records ๐. So GNS defines the BOX record format to box those up and include them in the record set of the label they belong to โจ. For example, a TLSA record for "_https._tcp.example.org" gets stored in the record set of "example.org" as a BOX record with service (SVC) 443 (https), protocol (PROTO) 6 (tcp), and record TYPE "TLSA" ๐ธ. For reference, see also [RFC2782] ๐. Here's the BOX DATA entry in Figure 17:
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| PROTO | SVC | TYPE |
+-----------+-----------------------------------+
| RECORD DATA |
/ /
/ /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 17: The BOX DATA Wire Format
PROTO: the 16-bit protocol number in network byte order. Values below 2^8 are reserved for 8-bit Internet Protocol numbers allocated by IANA [RFC5237] (e.g., 6 for TCP). Values above 2^8 are allocated by the GANA "GNUnet Overlay Protocols" registry [GANA] ๐ง.
SVC: the 16-bit service value of the boxed record in network byte order. For TCP and UDP, it's the port number ๐.
TYPE: the 32-bit record type of the boxed record in network byte order ๐.
RECORD DATA: a variable-length field holding the "DATA" format of TYPE, as defined for each TYPE. So for TYPE values below 2^16, the format is the same as that record type's binary format in DNS ๐.
- Record Encoding for Remote Storage ๐ฆ
Any API that lets you store a block under a 512-bit key and retrieve one or more blocks from a key can be used by an implementation for remote storage ๐. To be useful, and to support the defined zone delegation record encodings, the API MUST permit storing blocks of size 176 bytes or more and SHOULD allow blocks of size 1024 bytes or more ๐ฅ. Here, an implementation is assumed to realize two procedures on top of storage:
PUT(key, block)
GET(key) -> block
A GNS implementation publishes blocks according to the properties and recommendations of the underlying remote storage. That can include a periodic refresh operation to keep published blocks available ๐ซถ.
There's no mechanism for explicitly deleting individual blocks from remote storage ๐. However, blocks include an EXPIRATION field, which guides remote storage implementations in deciding when to delete blocks โณ. Given multiple blocks for the same key, remote storage implementations SHOULD try to preserve and return the block with the largest EXPIRATION value ๐.
All resource records from the same zone sharing the same label are encrypted and published together in a single resource record block (RRBLOCK) in remote storage under a key q, as shown in Figure 18 โจ. A GNS implementation MUST NOT include expired resource records in blocks. An implementation MUST use the PUT storage procedure when record sets change, to update the zone contents. Implementations MUST ensure that the EXPIRATION fields of RRBLOCKs increase strictly monotonically for every change, even if the smallest expiration time of records in the block doesn't increase ๐ .
Local Host | Remote
| Storage
|
| +---------+
| / /|
| +---------+ |
+-----------+ | | | |
| | +-----------+PUT(q, RRBLOCK) | | Record | |
| User | | Zone |----------------|->| Storage | |
| | | Publisher | | | |/
+-----------+ +-----------+ | +---------+
| A |
| | Zone records |
| | grouped by label |
| | |
| +---------+ |
|Create / Delete / | /| |
|and Update +---------+ | |
|Local Zones | | | |
| | Local | | |
+-------------->| Zones | | |
| |/ |
+---------+ |
Figure 18: Management and Publication of Local Zones in
Distributed Storage
Storage key derivation and record block creation are specified in the following sections and illustrated in Figure 19 ๐ง.
+----------+ +-------+ +------------+ +-------------+
| Zone Key | | Label | | Record Set | | Private Key |
+----------+ +-------+ +------------+ +-------------+
| | | |
| | v |
| | +-----------+ |
| +---------->| S-Encrypt | |
+----------|---------->+-----------+ |
| | | | |
| | | v v
| | | +-------------+
| +---------------|-->| SignDerived |
| | | +-------------+
| | | |
| v v v
| +------+ +--------------+
+----->| ZKDF |------->| Record Block |
+------+ +--------------+
|
v
+------+ +-------------+
| Hash |------->| Storage Key |
+------+ +-------------+
Figure 19: Storage Key and Record Block Creation Overview
6.1. The Storage Key ๐
The storage key is derived from the zone key and the respective label of the contained records ๐. The required knowledge of both the zone key and the label, combined with the similarly derived symmetric secret keys and blinded zone keys, is what ensures query privacy (see [RFC8324], Section 3.5) ๐ซถ.
Given a label, the storage key q is derived as follows:
q := SHA-512(ZKDF(zkey, label))
label: a UTF-8 string under which the resource records are published ๐ธ.
zkey: the zone key ๐ฆ.
q: the 512-bit storage key under which the resource record block is published ๐. It is the SHA-512 hash [RFC6234] over the derived zone key โจ.
6.2. Plaintext Record Data (RDATA) ๐
okay so GNS records in a zone get grouped by their labels, which means every record under the same label gets published together as one single block in storage ๐ฆ these grouped record sets MAY be paired with supplemental records too โจ
RDATA is the format used to encode one of those groups. Figure 20 shows the binary layout ๐
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| EXPIRATION |
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIZE | FLAGS | TYPE |
+-----+-----+-----+-----+-----+-----+-----+-----+
| DATA /
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
| EXPIRATION |
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIZE | FLAGS | TYPE |
+-----+-----+-----+-----+-----+-----+-----+-----+
| DATA /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
| PADDING /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 20: The RDATA Wire Format
- EXPIRATION, SIZE, TYPE, FLAGS, and DATA: the definitions for these fields are given below Figure 7 in Section 5, so go check there ๐ง
- PADDING: when you serialize records into RDATA, a GNS implementation MUST ensure that the size of the RDATA is a power of two using this field. The field MUST be set to zero and MUST be ignored on receipt. as a special exception ๐ record sets with (only) a zone delegation record type are never padded
6.3. The Resource Record Block ๐
okay this part is giving encryption energy ๐ the resource records grouped in an RDATA get encrypted using the S-Encrypt() function defined by the zone type of the zone they belong to, and then they get prefixed with metadata into a resource record block (RRBLOCK) for remote storage. The GNS RRBLOCK wire format is shown in Figure 21 โจ
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIZE | ZONE TYPE |
+-----+-----+-----+-----+-----+-----+-----+-----+
| ZONE KEY /
/ (BLINDED) /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIGNATURE |
/ /
/ /
| |
+-----+-----+-----+-----+-----+-----+-----+-----+
| EXPIRATION |
+-----+-----+-----+-----+-----+-----+-----+-----+
| BDATA |
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 21: The RRBLOCK Wire Format
- SIZE: a 32-bit value with the length of the block in bytes, in network byte order. even though the message format uses a 32-bit value ๐ implementations MAY refuse to publish blocks beyond a certain size significantly below the theoretical block size limit of 4 GB
- ZONE TYPE: the 32-bit ztype in network byte order
- ZONE KEY (BLINDED): the blinded zone key
ZKDF(zkey, label), which is used to verify SIGNATURE. the length and format of the blinded public key depend on the ztype - SIGNATURE: the signature is computed over the EXPIRATION and BDATA fields, as shown in Figure 22. the length and format of the signature depend on the ztype. it's created using the SignDerived() function of the cryptosystem of the zone (see Section 4) ๐
- EXPIRATION: this tells you when the RRBLOCK expires. the encrypted block SHOULD be removed from storage and caches, since it's likely stale ๐ฅ however, applications MAY continue to use non-expired individual records until they expire. the RRBLOCK expiration value MUST be computed by first working out, for each record type in the RRBLOCK, the maximum expiration time of all records of that type, including shadow records. then you take the minimum of all those expiration times. the final expiration time is the larger value of (1) the previous EXPIRATION value of a previous RRBLOCK for the same storage key plus one (if any), and (2) the computed minimum expiration time across the contained record types. this is what ensures strict monotonicity (see Section 9.3) ๐ it's a 64-bit absolute date in microseconds since midnight (0 hour), January 1, 1970 UTC, in network byte order
- BDATA: the encrypted RDATA, computed using S-Encrypt() with the zone key, label, and expiration time as additional inputs. its ultimate size and content are determined by the S-Encrypt() function of the ztype ๐ซถ
the signature over the public key covers a 32-bit pseudo header that's conceptually prefixed to the EXPIRATION and BDATA fields. the wire format is shown in Figure 22 ๐
0 8 16 24 32 40 48 56
+-----+-----+-----+-----+-----+-----+-----+-----+
| SIZE | PURPOSE (0x0F) |
+-----+-----+-----+-----+-----+-----+-----+-----+
| EXPIRATION |
+-----+-----+-----+-----+-----+-----+-----+-----+
| BDATA |
/ /
/ /
+-----+-----+-----+-----+-----+-----+-----+-----+
Figure 22: The Wire Format Used for Creating the Signature of the RRBLOCK
- SIZE: a 32-bit value with the length of the signed data in bytes, in network byte order
- PURPOSE: a 32-bit signature purpose flag in network byte order. the value of this field MUST be 15 ๐ฏ it defines the context the signature is created in, so it can't be reused in other parts of the protocol that might include possible future extensions. the value corresponds to an entry in the GANA "GNUnet Signature Purposes" registry [GANA]
- EXPIRATION: field as defined in the RRBLOCK message above
- BDATA: field as defined in the RRBLOCK message above
7. Name Resolution ๐ฆ
okay so names in GNS get resolved by recursively querying the record storage. "recursive" here means a resolver does NOT hand intermediate results back to the application. instead, it MUST respond to a resolution request with either the requested resource record or an error message if resolution fails ๐ โโ๏ธ Figure 23 shows how an application requests the lookup of a GNS name (1). the application MAY provide a desired record type to the resolver ๐ then a Start Zone is determined (2) and the recursive resolution process kicks off. this is where the desired record type steers things. for example, if a zone delegation record type is requested, resolving the apex label in that zone gets skipped, since the desired record is already found โจ the details on how the resolution process starts and how each iterative result (3a,3b) gets handled are in the sections below. the results of the lookup are eventually returned to the application (4) ๐
the implementation MUST NOT filter the returned resource record sets according to the desired record type. filtering record sets is typically done by the application, not the resolver ๐
Local Host | Remote
| Storage
|
| +---------+
| / /|
| +---------+ |
+-----------+ (1) Name +----------+ | | | |
| | Lookup | | (3a) GET(q) | | Record | |
|Application|----------| Resolver |---------------|->| Storage | |
| |<---------| |<--------------|--| |/
+-----------+ (4) +----------+ (3b) RRBLOCK | +---------+
Records A |
| |
(2) Determination of | |
Start Zone | |
| |
+---------+ |
/ | /| |
+---------+ | |
| | | |
| Start | | |
| Zones | | |
| |/ |
+---------+ |
Figure 23: The Recursive GNS Resolution Process
7.1. Start Zones ๐ธ
okay so resolving a GNS name starts with figuring out the Start Zone suffix ๐ . Once you've got that, recursive resolution of the rest of the name kicks off (see Section 7.2). There are two kinds of Start Zone suffixes: zTLDs and local suffix-to-zone mappings. Which suffix-to-zone mappings you have is totally up to the local system administrator or user ๐ฆ. This dodges the whole single-hierarchy-with-a-centrally-controlled-root situation, plus the related headache of distributing and managing root servers in DNS (see Sections 3.12 and 3.10 of [RFC8324], respectively). Iconic, honestly โจ.
For names ending with a zTLD, the Start Zone is spelled right out in the suffix of the name you're resolving ๐ง. To keep names with zTLDs unique, any implementation MUST use the given zone as the Start Zone. An implementation MUST first try to read the rightmost label as the start of a zTLD (see Section 4.1). If that label can't be (even partially) decoded, or it doesn't point to a supported ztype, the name gets treated like a normal name, and Start Zone discovery MUST continue by looking for a local suffix-to-zone mapping. If the rightmost label does have a valid ztype, the implementation MUST try to synthesize and decode the zTLD to get the Start Zone key, following Section 4.1. If the zTLD can't be synthesized or decoded, resolution fails and an error goes back to the app ๐. Otherwise, the zone key MUST be used as the Start Zone:
Example name: www.example.<zTLD>
=> Start Zone: zkey of type ztype
=> Name to resolve from Start Zone: www.example
For names not ending with a zTLD, the resolver MUST work out the Start Zone through a local suffix-to-zone mapping. Those mappings MUST be configurable through a local configuration file or database, set by the user or system administrator. A suffix MAY be made up of multiple GNS labels joined together with a label separator. If more than one suffix matches the name to resolve, the longest matching suffix MUST be used. The suffix length of two results MUST NOT be equal, because that means something's misconfigured, and the implementation MUST return an error ๐. Here's a non-normative example of Start Zone mappings:
Example name: www.example.xyz.gns.alt
Local suffix mappings:
xyz.gns.alt = zTLD0 := Base32GNS(ztype0||zkey0)
example.xyz.gns.alt = zTLD1 := Base32GNS(ztype1||zkey1)
example.com.gns.alt = zTLD2 := Base32GNS(ztype2||zkey2)
...
=> Start Zone: zkey1
=> Name to resolve from Start Zone: www
The process above MAY be supplemented with other mechanisms if a particular application needs something different. If no Start Zone can be identified, resolution MUST fail and an error MUST be returned to the application.
7.2. Recursion โจ
In each step of recursive name resolution, there's an authoritative zone zkey and a name to resolve. The name MAY be empty. If it is empty, it gets interpreted as the apex label @. At the very beginning, the authoritative zone is the Start Zone.
From there, the following steps run recursively, in order:
- Pull out the rightmost label from the name you're looking up.
- Calculate
qfrom the label andzkey, as defined in Section 6.1. - Make a storage query
GET(q)to fetch theRRBLOCK. - Check that (a) the block isn't expired, (b) the SHA-512 hash of the derived authoritative zone key
zkey'from theRRBLOCKmatches the queryq, and (c) the signature is valid. If any of these tests fail, theRRBLOCKMUST be ignored and, if applicable, the storage lookupGET(q)MUST continue looking for otherRRBLOCKs. - Get the
RDATAby decrypting theBDATAin theRRBLOCKusingS-Decrypt()as defined by the zone type. Basically, this reverses the process described in Section 6.3.
Once a well-formed block has been decrypted, the records from RDATA go through record processing ๐.
7.3. Record Processing ๐ฅ
In record processing, only the valid records we got are considered. To filter records by validity, the resolver MUST at least check the expiration time and the FLAGS field of each respective record. Specifically, the resolver MUST disregard expired records. The SHADOW and SUPPLEMENTAL flags can also knock records out of consideration. If the resolver runs into a record with the CRITICAL flag set and doesn't support that record type, resolution MUST be aborted and an error MUST be returned. Information saying the critical record couldn't be processed SHOULD be returned in the error description. The implementation MAY choose not to return the reason for the failure, which just makes troubleshooting harder for the poor user ๐ญ.
The next steps depend on the context of the name being resolved:
- Case 1: If the filtered record set is a single REDIRECT record, the rest of the name gets prepended to the REDIRECT DATA, and recursion starts over from the resulting name. The details are in Section 7.3.1.
- Case 2: If the filtered record set is nothing but one or more GNS2DNS records, resolution continues with DNS. The details are in Section 7.3.2.
- Case 3: If the rest of the name to be resolved is of the format
_SERVICE._PROTOand the record set contains one or more matching BOX records, the records inside the BOX records are the final result, and recursion ends as described in Section 7.3.3. - Case 4: If the current record set is a single delegation record, resolving the rest of the name gets handed off to the target zone, as described in Section 7.3.4.
- Case 5: If there's nothing left of the name to resolve, the record set is the final result. If any NICK records are in the final result set, they MUST first be processed according to Section 7.3.5. Otherwise, the record result set is returned directly as the final result.
Finally, if none of the cases above apply, resolution fails, and the resolver MUST return an empty record set ๐ฅ.
7.3.1. REDIRECT ๐
If the remaining name is empty and the desired record type is REDIRECT, resolution wraps up with the REDIRECT record. If the rightmost label of the REDIRECT NAME is the extension label U+002B ("+"), resolution carries on in GNS with the new name in the current zone. Otherwise, the resulting name goes through the default operating system name resolution process. That can trigger a GNS name resolution process of its own, depending on the system configuration. If resolution continues in DNS, the name MUST first be converted to an IDNA-compliant representation [RFC5890].
To prevent infinite loops, the resolver MUST implement loop detection or limit the number of recursive resolution steps. The loop detection MUST stay effective even if a REDIRECT found in GNS triggers later GNS lookups through the default operating system name resolution process. no endless loops, bestie ๐
7.3.2. GNS2DNS ๐
A resolver returns GNS2DNS records when all of the following conditions are met:
- The resolver encounters one or more GNS2DNS records;
- The remaining name is empty; and
- The desired record type is GNS2DNS.
Otherwise, the resolver is expected to first resolve the IP addresses of the specified DNS name servers. The DNS name MUST be converted to an IDNA-compliant representation [RFC5890] for resolution in DNS. GNS2DNS records MAY contain numeric IPv4 or IPv6 addresses, which lets the resolver skip this step. The DNS server names might themselves be names in GNS or DNS. If the rightmost label of the DNS server name is the extension label U+002B ("+"), the rest of the name is interpreted relative to the zone of the GNS2DNS record. If the DNS server name ends in a label representation of a zone key, the DNS server name is resolved against the GNS zone zkey.
Multiple GNS2DNS records can be stored under the same label, in which case the resolver MUST try all of them. The resolver MAY try them in any order or even in parallel. If multiple GNS2DNS records are present, the DNS name MUST be identical for all of them. Otherwise, it isn't clear which name the resolver is supposed to follow. If different DNS names are present, resolution fails, and an appropriate error SHOULD be returned to the application.
If there are DNSSEC DS records, or any other records used to secure the connection with the DNS servers, stored under the label, the DNS resolver SHOULD use them to secure the connection with the DNS server ๐.
Once the IP addresses of the DNS servers have been determined, the DNS name from the GNS2DNS record is appended to the remainder of the name to be resolved, and it's resolved by querying the DNS name server(s). The synthesized name has to be converted to an IDNA-compliant representation [RFC5890] for resolution in DNS. If that conversion isn't possible, resolution MUST be aborted and an error MUST be returned. Information indicating that the critical record could not be processed SHOULD be returned in the error description. The implementation MAY choose not to return the reason for the failure, which just makes troubleshooting harder for the user.
Since the DNS servers specified are possibly authoritative DNS servers, the GNS resolver MUST support recursive DNS resolution and MUST NOT delegate this to the authoritative DNS servers. The first successful recursive name resolution result is returned to the application. On top of that, the resolver SHOULD return the queried DNS name as a supplemental LEHO record (see Section 5.3.1) with a relative expiration time of one hour โฐ.
Once the transition from GNS to DNS is made through a GNS2DNS record, there is no "going back" ๐ซ. The (possibly recursive) resolution of the DNS name MUST NOT delegate back into GNS and should only follow the DNS specifications. For example, names contained in DNS CNAME records MUST NOT be interpreted by resolvers that support both DNS and GNS as GNS names.
GNS resolvers SHOULD offer a configuration option to disable DNS processing, to avoid information leakage and provide a consistent security profile for all name resolutions. Such resolvers would return an empty record set upon encountering a GNS2DNS record during the recursion. However, if GNS2DNS records are encountered in the record set for the apex label, and a GNS2DNS record is explicitly requested by the application, such records MUST still be returned, even if DNS support is disabled by the GNS resolver configuration ๐ง.
7.3.3. BOX ๐
When a BOX record is received, a GNS resolver must unbox it if the name to be resolved continues with _SERVICE._PROTO. Otherwise, the BOX record is to be left untouched. This way, TLSA (and SRV) records do not require a separate network request, and TLSA records become inseparable from the corresponding address records ๐ฆ.
7.3.4. Zone Delegation Records โจ
okay bestie, so when the resolver spots a zone delegation record type it knows (like PKEY or EDKEY) and there's still stuff left over in the name, it keeps going recursively with the leftover part of the name inside the GNS zone that the delegation record points to ๐ฆ
Whenever a resolver runs into a new GNS zone, it MUST check the local revocation list (see Section 4.2) to see if that zone key got revoked ๐ซ. If the zone key was revoked, the resolution MUST fail with an empty result set ๐.
Implementations MUST NOT allow multiple different zone delegations under a single label (except if some are shadow records) ๐ โโ๏ธ. Implementations MAY support any subset of ztypes ๐ธ. Implementations MUST NOT process zone delegation records stored under the apex label ("@") ๐ โโ๏ธ. If one shows up under the apex label, resolution fails and an error MUST be returned. The implementation MAY choose not to return the reason for the failure, which only affects the troubleshooting info the user gets ๐.
If the remainder of the name is empty and the record set only has a single delegation record, recursion keeps going with the record value as the authoritative zone, using the apex label "@" as the remaining name โจ. The one exception: if the record type the application asked for is equal to the ztype, the delegation record itself gets returned ๐.
7.3.5. NICK ๐
okay NICK records only matter to the recursive resolver when the record set is the final result that's going back to the application ๐ . The NICK records it runs into can be either supplemental (see Section 5) or non-supplemental. If the NICK record is supplemental, the resolver only returns the record set if one of the non-supplemental records matches the queried record type. It's possible for one record set to contain both supplemental and non-supplemental NICK records ๐.
The difference between a supplemental and a non-supplemental NICK record is what lets the application match the record to the authoritative zone ๐. Check out this example:
Query: alice.example.gns.alt (type=A)
Result:
A: 192.0.2.1
NICK: eve (non-supplemental)
Here the returned NICK record is non-supplemental. For the application, that means the NICK belongs to the zone "alice.example.gns.alt" and is published under the apex label right next to an A record. So the NICK is read like this: the zone defined by "alice.example.gns.alt" wants to be called "eve" โญ. Now compare this one:
Query: alice.example.gns.alt (type=AAAA)
Result:
AAAA: 2001:db8::1
NICK: john (supplemental)
This time the NICK record is marked as supplemental, so it belongs to the zone "example.gns.alt" and is published under the label "alice" alongside an AAAA record ๐ง. Here the NICK should be read like this: the zone defined by "example.gns.alt" wants to be called "john". This distinction is likely useful for other records published as supplemental ๐ฆ.
8. Internationalization and Character Encoding ๐
Every name in GNS is encoded in UTF-8 [RFC3629] ๐. Labels MUST be canonicalized using Normalization Form C (NFC) [Unicode-UAX15] โจ. This doesn't cover any DNS names found in DNS records, like CNAME record data. Those are internationalized through the IDNA specifications instead; see [RFC5890] ๐ธ.
9. Security and Privacy Considerations ๐
Okay, this part is seriously important, so pay attention ๐ซถ.
9.1. Availability โฐ
To keep records available past their absolute expiration times, implementations MAY allow relative expiration time values of records to be defined locally. Records can then get published again, recurringly, with updated absolute expiration times by the implementation ๐.
Implementations MAY allow users to manage private records in their zones that are not published in storage. Private records get treated just like regular records when labels are resolved in local zones, but their data is completely unavailable to non-local users ๐.
9.2. Agility ๐ก๏ธ
The security of a cryptographic system depends on both how strong the algorithms are and how strong the keys are ๐. It also depends on how the protocol using them is engineered, so there are no non-cryptographic ways to bypass the security of the whole system ๐. That's why developers of applications managing GNS zones SHOULD select a default ztype that's considered secure at the time they release the software. For applications aimed at end users who aren't expected to understand cryptography, the application developer MUST NOT leave the ztype selection of new zones to those end users ๐ซ.
This document is all about choosing which cryptographic algorithms GNS uses ๐ . The algorithms identified here aren't known to be broken (in the cryptographic sense) right now, and cryptographic research so far suggests they're likely to stay secure for the foreseeable future. But that's not forever, so new revisions of this document are expected to come out from time to time to reflect current best practices ๐.
When it comes to crypto-agility: whenever an updated cryptographic scheme is needed, say to replace ECDSA over Ed25519 for PKEY records, it can simply be introduced through a new record type โจ. Zone administrators can then swap the delegation record type for future records. The old record type sticks around, so zones can migrate to the updated zone keys bit by bit ๐ฆ. To make sure implementations correctly generate an error message when they hit a ztype they don't support, current and future delegation records must always have the CRITICAL flag set ๐ฉ.
9.3. Cryptography ๐ฌ
The following considerations give background on the design choices behind the ztypes specified in this document ๐ง . When specifying new ztypes as per Section 4, the same considerations apply ๐.
GNS PKEY zone keys use ECDSA over Ed25519. Yes, this is an unconventional choice, since ECDSA is usually used with other curves ๐. But standardized ECDSA curves are problematic for a range of reasons, as described in the Curve25519 and EdDSA papers [RFC7748] [ed25519] ๐. Using EdDSA directly isn't possible either, because a hash function is applied to the private key, and that would destroy the linearity that GNS key blinding depends on ๐. We're not aware of anyone suggesting that using Ed25519 instead of another common curve of similar size would lower the security of ECDSA. GNS uses 256-bit curves, which means the encoded (public) keys fit into a single DNS label, and that's great for usability ๐ฅฐ.
To keep ciphertext indistinguishable, you have to be careful with the IV in the counter block ๐. In this design, the IV always includes the expiration time of the record block. When applications store records with relative expiration times, monotonicity is implicitly ensured, because each time a block is published in storage its IV is unique. The expiration time is calculated dynamically and increases monotonically with the system time ๐ฐ๏ธ. Still, an implementation MUST ensure that when relative expiration times are decreased, the expiration time of the next record block MUST be after the last published block. For records where an absolute expiration time is used, the implementation MUST ensure that the expiration time is always increased when the record data changes. For example, the expiration time on the wire could be increased by a single microsecond even if the user didn't ask for a change ๐.
If all resource records under a label get deleted, the implementation MUST keep track of the last absolute expiration time of the last published resource block ๐. Implementations MAY define and use a special record type as a tombstone that preserves the last absolute expiration time, but then they MUST take care not to publish a block with such a tombstone record ๐ชฆ. When new records are added under this label later, the implementation MUST ensure that the expiration times are after the last published block. Finally, to keep expiration times monotonically increasing, the implementation MUST keep a local record of the last time obtained from the system clock, so it can construct a monotonic clock if the system clock jumps backwards โช.
9.4. Abuse Mitigation ๐จ
GNS names are UTF-8 strings, so GNS has to deal with name spoofing issues similar to the ones DNS has with internationalized domain names ๐. In DNS, attackers can register similar-sounding or similar-looking names (see above) to pull off phishing attacks ๐ฃ. GNS zone administrators must take this attack vector into account and build in rules to mitigate it ๐.
Also, DNS can be used to fight illegal content on the Internet by having the relevant domains seized by authorities. But those same mechanisms can be abused to impose state censorship ๐ฌ. Avoiding that possibility is one of the motivations behind GNS ๐ฆ. In GNS, TLDs aren't enumerable. By design, the resolver's Start Zone is defined locally, so a seizure is difficult and ineffective in GNS ๐ช.
9.5. Zone Management ๐๏ธ
In GNS, zone administrators need to manage and protect their zone keys ๐. Once a private zone key is lost, it can't be recovered, and the zone revocation message can't be computed anymore. Revocation messages can be precalculated if revocation is needed in cases where a private zone key gets lost ๐ . Zone administrators, and for GNS that includes end users, are required to responsibly and diligently protect their cryptographic keys ๐. GNS supports signing records in advance ("offline") so that processes (such as air gaps) that aim to protect private keys can be used ๐ง.
Similarly, users are required to manage their local Start Zone configuration ๐ . To keep names intact and available, users must make sure their local Start Zone information isn't compromised or outdated โ ๏ธ. It can be expected that zone revocations and an initial Start Zone get shipped with a GNS implementation ("drop shipping") ๐ฆ. Shipping an initial Start Zone configuration effectively establishes a root zone ๐. Extending and customizing the zone is entirely up to the user ๐จ.
While implementations following this specification will be interoperable, if two implementations connect to different remote storage entities, they're mutually unreachable ๐ โโ๏ธ. This can lead to a state where a record exists in the global namespace for a particular name, but the implementation isn't talking to the remote storage entity that holds the respective block, so it can't resolve it ๐ญ. It's kind of like a split-horizon DNS setup ๐. Which remote storage entity gets used will most likely depend on the specific application context using GNS resolution. For example, resolving hidden services within the Tor network [TorRendSpec] would suggest using Tor routers for remote storage ๐ง . Implementations of "aggregated" remote storage entities are conceivable, but they're expected to be the exception ๐.
9.6. DHTs as Remote Storage ๐ง
okay bestie, this one's lowkey a big deal ๐ this doc does NOT spell out how the underlying remote storage works ๐, but every GNS implementation needs some, so it matters. the storage's properties get passed straight down to the GNS implementation (no cap, it's inherited ๐ซถ). that includes security AND the non-functional stuff like scalability and performance ๐. implementers should take SO much care when picking or building a DHT to use as remote storage ๐ it's honestly the most important choice they'll make. DHTs with reasonable security and performance properties do exist [R5N] โจ. it should also be considered that GNS implementations built on different DHT overlays are unlikely to be mutually reachable ๐ญ they might not be able to see each other, which is so not the vibe.
9.7. Revocations ๐
zone administrators are advised to pregenerate zone revocations and to securely store the revocation information if the zone key is lost, compromised, or replaced in the future ๐. precalculated revocations can stop being valid because of expirations or protocol changes like epoch adjustments, so implementers and users must take precautions to manage revocations properly ๐งน.
revocation payloads do not include a "new" key for key replacement. and honestly? that's on purpose ๐ โโ๏ธ including one would cause two major problems:
- if a revocation gets published after a private key was compromised, allowing key replacement would be dangerous ๐ฑ. if an adversary took over the private key, they could broadcast a revocation with a key replacement. the compromised owner would have no chance to issue a revocation for it. so letting a revocation message replace a private key makes key compromise situations WORSE, not better.
- sometimes key revocations are used to change cryptosystems ๐. migrating to another cryptosystem by replacing keys via a revocation message would only be secure as long as both cryptosystems are still secure against forgery. a planned, non-emergency migration should be done by running zones for both cipher systems in parallel for a while ๐ซง. the migration would wrap up by revoking the legacy zone key only once it's deemed no longer secure and, hopefully, after most users have moved over to the replacement ๐.
9.8. Zone Privacy ๐ต๏ธโโ๏ธ
GNS does NOT support authenticated denial of existence of names within a zone ๐ . record data is published in encrypted form, using keys derived from the zone key and the record label ๐. zone administrators should carefully think about whether (1) a label and zone key are public or (2) one or both should be used as a shared secret to restrict access to the corresponding record data ๐คซ. here's the tea: unlike public zone keys, low-entropy labels can be guessed by an attacker ๐. if an attacker knows the public zone key, using well-known or guessable labels effectively threatens the disclosure of the corresponding records ๐ฌ.
it's worth noting that the guessing attack on labels only applies if the zone key is somehow disclosed to the adversary ๐ง . GNS itself does not disclose it during a lookup or when resource records are published (since only the blinded zone keys are used on the network) ๐. however, zone keys DO become public during revocation โ ๏ธ.
it is thus RECOMMENDED to use a label with sufficient entropy to prevent guessing attacks if any data in a resource record set is sensitive. no skipping this one, bestie ๐จ
9.9. Zone Governance ๐๏ธ
while DNS is distributed, in practice it relies on centralized, trusted registrars to provide globally unique names ๐. as people get more aware of how central DNS is to the Internet, various institutions are using their power (including legal means) to attack the DNS, which threatens the global availability and integrity of information on the Internet ๐ค. a wider discussion of this is out of scope for this document, but analyses and investigations can be found in recent academic research works, including [SecureNS] ๐.
GNS is designed to be a secure, privacy-enhancing alternative to the DNS name resolution protocol, especially when censorship or manipulation shows up ๐ก๏ธ. it directly addresses DNS concerns about query privacy โจ. however, depending on the governance of the root zone, any deployment will likely suffer from the issue of a single hierarchy with a centrally controlled root, plus the related issue of distributing and managing root servers in DNS, as raised in Sections 3.12 and 3.10 of [RFC8324] respectively ๐ณ. in DNS, those issues come directly from the centralized root zone governance at the Internet Corporation for Assigned Names and Numbers (ICANN), which lets it provide globally unique names ๐.
in GNS, Start Zones give users local authority over their preferred root zone governance ๐. users can replace or enhance a trusted root zone configuration provided by a third party (e.g., the implementer or a multi-stakeholder governance body like ICANN) with secure delegation of authority using local petnames ๐ฅฐ, all while operating under a very strong adversary model ๐ช. combined with zTLDs, this gives GNS users a global, secure, and memorable mapping without a trusted authority ๐ฆ.
any GNS implementation MAY provide a default governance model in the form of an initial Start Zone mapping ๐.
9.10. Namespace Ambiguity ๐ซฃ
technically, the GNS protocol CAN be used to resolve names in the namespace of the global DNS ๐คฏ. but that would require the respective governance bodies and stakeholders (e.g., the IETF and ICANN) to standardize the use of GNS for this particular use case ๐.
this capability means GNS names may be indistinguishable from DNS names in their common display format [RFC8499], or from other special-use domain names [RFC6761], if a local Start Zone configuration maps suffixes from the global DNS to GNS zones ๐. applications then become confused about which name system should resolve a given name ๐. this is a risk when trying to resolve a name through DNS when it's actually a GNS name, as discussed in [RFC8244] ๐ฉ. in that case, the GNS name is likely to be leaked as part of the DNS resolution ๐ญ.
to prevent disclosure of queried GNS names, it is RECOMMENDED that GNS-aware applications try to resolve a given name in GNS before any other method, taking into account potential suffix-to-zone mappings and zTLDs ๐. suffix-to-zone mappings are expected to be configured by the user or a local administrator, so resolving in GNS matches user expectations even if the name could also be resolved through DNS ๐. if no suffix-to-zone mapping exists for the name and no zTLD is found, resolution MAY continue with other methods such as DNS ๐ซง. but if a suffix-to-zone mapping exists for the name or the name ends with a zTLD, it MUST be resolved using GNS, and resolution MUST NOT continue by any other means, regardless of the GNS resolution result ๐ซ.
mechanisms like the Name Service Switch (NSS) of UNIX-like operating systems are an example of how this resolution process can be implemented and used ๐ง. the NSS lets system administrators configure hostname resolution precedence, and it's integrated with the system resolver implementation ๐งฉ.
for use cases where GNS names may be confused with names from other name resolution mechanisms (in particular, DNS), the ".gns.alt" domain SHOULD be used ๐ท๏ธ. for use cases like implementing sinkholes to block malware sites, or serving DNS domains via GNS to bypass censorship, GNS MAY be deliberately used in ways that interfere with resolution of another name system ๐ ๏ธ. (we love a deliberate plot twist, but know what you're doing ๐.)
10. GANA Considerations ๐ท
10.1. GNUnet Signature Purposes Registry
GANA [GANA] has assigned signature purposes in its "GNUnet Signature Purposes" registry, as listed in Table 1 ๐.
+=========+=================+============+==========================+
| Purpose | Name | References | Comment |
+=========+=================+============+==========================+
| 3 | GNS_REVOCATION | RFC 9498 | GNS zone key revocation |
+---------+-----------------+------------+--------------------------+
| 15 | GNS_RECORD_SIGN | RFC 9498 | GNS record set |
| | | | signature |
+---------+-----------------+------------+--------------------------+
Table 1: The GANA GNUnet Signature Purposes Registry
10.2. GNS Record Types Registry โจ
Okay bestie, GANA [GANA] is the one managing the "GNS Record Types" registry ๐ Every entry has the following format:
- Name: the name of the record type. It's a case-insensitive ASCII string, limited to alphanumeric characters. For zone delegation records, the assigned number is the
ztypevalue of the zone ๐ฆ - Number: a 32-bit number above 65535 ๐ข
- Comment: optional, brief English text about what the record type is for (in UTF-8) ๐ฌ
- Contact: optional, contact info for a person you can reach for more details ๐
- References: optional, references (like an RFC) that describe the record type ๐
The registration policy here is "First Come First Served" ๐ It's modeled on the one in [RFC8126], and this is what GANA does:
- Adding new entries is possible after review by any authorized GANA contributor, using a first-come-first-served policy for unique name allocation. Reviewers are responsible for making sure the chosen "Name" fits the record type. The registry will define a unique number for the entry.
- Authorized GANA contributors who review new entries can be reached at
<gns-registry@gnunet.org>๐ - Any request MUST contain a unique name and a point of contact. The contact information MAY be added to the registry, with the consent of the requester. The request MAY optionally also contain relevant references as well as a descriptive comment, as defined above. ๐ซถ
GANA has assigned numbers for the record types defined in this specification in the "GNS Record Types" registry, and they're listed in Table 2 ๐
+========+==========+=========+============+====================+
| Number | Name | Contact | References | Comment |
+========+==========+=========+============+====================+
| 65536 | PKEY | (*) | RFC 9498 | GNS zone |
| | | | | delegation (PKEY) |
+--------+----------+---------+------------+--------------------+
| 65537 | NICK | (*) | RFC 9498 | GNS zone nickname |
+--------+----------+---------+------------+--------------------+
| 65538 | LEHO | (*) | RFC 9498 | GNS legacy |
| | | | | hostname |
+--------+----------+---------+------------+--------------------+
| 65540 | GNS2DNS | (*) | RFC 9498 | Delegation to DNS |
+--------+----------+---------+------------+--------------------+
| 65541 | BOX | (*) | RFC 9498 | Box records |
+--------+----------+---------+------------+--------------------+
| 65551 | REDIRECT | (*) | RFC 9498 | Redirection record |
+--------+----------+---------+------------+--------------------+
| 65556 | EDKEY | (*) | RFC 9498 | GNS zone |
| | | | | delegation (EDKEY) |
+--------+----------+---------+------------+--------------------+
| (*): gns-registry@gnunet.org |
+---------------------------------------------------------------+
Table 2: The GANA GNS Record Types Registry
10.3. .alt Subdomains Registry โจ
GANA [GANA] manages the ".alt Subdomains" registry ๐ฆ Quick heads-up: this GANA-operated .alt registry may or may not be taken into account by any particular implementer, and it has zero official connection to the IETF or ICANN. Not sanctioned, not associated, just vibes ๐
Each entry has the following format:
- Label: the label of the subdomain, in DNS "letters, digits, hyphen" (LDH) format as defined in Section 2.3.1 of [RFC5890] ๐ค
- Description: optional, brief English text about what the subdomain is for (in UTF-8) ๐
- Contact: optional, contact info for a person you can reach for more details ๐
- References: optional, references (like an RFC) that describe the record type ๐
The registration policy here is also "First Come First Served" ๐ It's modeled on the one in [RFC8126], and GANA does the following:
- Adding new entries is possible after review by any authorized GANA contributor, using a first-come-first-served policy for unique subdomain allocation. Reviewers are responsible for making sure the chosen "Subdomain" fits the purpose.
- Authorized GANA contributors who review new entries can be reached at
<alt-registry@gnunet.org>๐ - Any request MUST contain a unique subdomain and a point of contact. The contact information MAY be added to the registry, with the consent of the requester. The request MAY optionally also contain relevant references as well as a descriptive comment, as defined above. โจ
GANA has assigned the subdomain defined in this specification in the ".alt Subdomains" registry, as listed in Table 3 ๐ธ
+=======+=========+============+============================+
| Label | Contact | References | Description |
+=======+=========+============+============================+
| gns | (*) | RFC 9498 | The .alt subdomain for GNS |
+-------+---------+------------+----------------------------+
| (*): alt-registry@gnunet.org |
+-----------------------------------------------------------+
Table 3: The GANA .alt Subdomains Registry
11. IANA Considerations ๐
Nothing for IANA to do here! This document has no IANA actions ๐ซถ
12. Implementation and Deployment Status โจ
Okay, the implementation scene is honestly iconic ๐ There are two implementations that conform to this specification, one written in C and one in Go. The C implementation, which is part of GNUnet [GNUnetGNS], is the original and reference implementation ๐ The Go implementation [GoGNS] shows how two GNS implementations can be interoperable when they're built on top of the same underlying DHT storage ๐ง
Right now, the GNUnet peer-to-peer network [GNUnet] is an active deployment of GNS running on its DHT [R5N] ๐ The Go implementation [GoGNS] uses this deployment by building on the GNUnet DHT services available on any GNUnet peer. It shows how GNS implementations can attach to this existing deployment and take part in both name resolution and zone publication ๐ฅ
The self-sovereign identity system re:claimID [reclaim] uses GNS to selectively share identity attributes and attestations with third parties ๐ฆ
Last but not least, the Ascension tool [Ascension] helps migrate DNS zones to GNS zones by translating information retrieved from a DNS zone transfer into a GNS zone ๐
13. References โจ
13.1. Normative References โจ
okay so this is the list of docs the spec leans on hardest, bestie ๐ each one comes with its number, title, authors, DOI, and link so you can go read them yourself ๐ค
[RFC1034]Mockapetris, P., "Domain names - concepts and facilities", STD 13, RFC 1034, DOI 10.17487/RFC1034, November 1987,https://www.rfc-editor.org/info/rfc1034.[RFC1035]Mockapetris, P., "Domain names - implementation and specification", STD 13, RFC 1035, DOI 10.17487/RFC1035, November 1987,https://www.rfc-editor.org/info/rfc1035.[RFC2782]Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for specifying the location of services (DNS SRV)", RFC 2782, DOI 10.17487/RFC2782, February 2000,https://www.rfc-editor.org/info/rfc2782.[RFC2119]Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,https://www.rfc-editor.org/info/rfc2119.[RFC3629]Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2003,https://www.rfc-editor.org/info/rfc3629.[RFC3686]Housley, R., "Using Advanced Encryption Standard (AES) Counter Mode With IPsec Encapsulating Security Payload (ESP)", RFC 3686, DOI 10.17487/RFC3686, January 2004,https://www.rfc-editor.org/info/rfc3686.[RFC3826]Blumenthal, U., Maino, F., and K. McCloghrie, "The Advanced Encryption Standard (AES) Cipher Algorithm in the SNMP User-based Security Model", RFC 3826, DOI 10.17487/RFC3826, June 2004,https://www.rfc-editor.org/info/rfc3826.[RFC5237]Arkko, J. and S. Bradner, "IANA Allocation Guidelines for the Protocol Field", BCP 37, RFC 5237, DOI 10.17487/RFC5237, February 2008,https://www.rfc-editor.org/info/rfc5237.[RFC5869]Krawczyk, H. and P. Eronen, "HMAC-based Extract-and-Expand Key Derivation Function (HKDF)", RFC 5869, DOI 10.17487/RFC5869, May 2010,https://www.rfc-editor.org/info/rfc5869.[RFC5890]Klensin, J., "Internationalized Domain Names for Applications (IDNA): Definitions and Document Framework", RFC 5890, DOI 10.17487/RFC5890, August 2010,https://www.rfc-editor.org/info/rfc5890.[RFC5895]Resnick, P. and P. Hoffman, "Mapping Characters for Internationalized Domain Names in Applications (IDNA) 2008", RFC 5895, DOI 10.17487/RFC5895, September 2010,https://www.rfc-editor.org/info/rfc5895.[RFC6234]Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, May 2011,https://www.rfc-editor.org/info/rfc6234.[RFC6895]Eastlake 3rd, D., "Domain Name System (DNS) IANA Considerations", BCP 42, RFC 6895, DOI 10.17487/RFC6895, April 2013,https://www.rfc-editor.org/info/rfc6895.[RFC6979]Pornin, T., "Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)", RFC 6979, DOI 10.17487/RFC6979, August 2013,https://www.rfc-editor.org/info/rfc6979.[RFC7748]Langley, A., Hamburg, M., and S. Turner, "Elliptic Curves for Security", RFC 7748, DOI 10.17487/RFC7748, January 2016,https://www.rfc-editor.org/info/rfc7748.[RFC8032]Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, January 2017,https://www.rfc-editor.org/info/rfc8032.[RFC8126]Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,https://www.rfc-editor.org/info/rfc8126.[RFC8174]Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017,https://www.rfc-editor.org/info/rfc8174.[RFC8499]Hoffman, P., Sullivan, A., and K. Fujiwara, "DNS Terminology", BCP 219, RFC 8499, DOI 10.17487/RFC8499, January 2019,https://www.rfc-editor.org/info/rfc8499.[RFC9106]Biryukov, A., Dinu, D., Khovratovich, D., and S. Josefsson, "Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications", RFC 9106, DOI 10.17487/RFC9106, September 2021,https://www.rfc-editor.org/info/rfc9106.[GANA]GNUnet e.V., "GNUnet Assigned Numbers Authority (GANA)", 2023,https://gana.gnunet.org/.[MODES]Dworkin, M., "Recommendation for Block Cipher Modes of Operation: Methods and Techniques", NIST Special Publication 800-38A, DOI 10.6028/NIST.SP.800-38A, December 2001,https://doi.org/10.6028/NIST.SP.800-38A.[CrockfordB32]Crockford, D., "Base 32", March 2019,https://www.crockford.com/base32.html.[XSalsa20]Bernstein, D. J., "Extending the Salsa20 nonce", 2011,https://cr.yp.to/papers.html#xsalsa.[Unicode-UAX15]Davis, M., Whistler, K., and M. Dรผrst, "Unicode Standard Annex #15: Unicode Normalization Forms", Revision 31, The Unicode Consortium, Mountain View, September 2009,https://www.unicode.org/reports/tr15/tr15-31.html.[Unicode-UTS46]Davis, M. and M. Suignard, "Unicode Technical Standard #46: Unicode IDNA Compatibility Processing", Revision 31, The Unicode Consortium, Mountain View, September 2023,https://www.unicode.org/reports/tr46.
13.2. Informative References ๐ฆ
these ones are the helpful background reads, the context and extra rabbit holes that make the spec click even though it doesn't lean on them as hard ๐ธ
[RFC1928]Leech, M., Ganis, M., Lee, Y., Kuris, R., Koblas, D., and L. Jones, "SOCKS Protocol Version 5", RFC 1928, DOI 10.17487/RFC1928, March 1996,https://www.rfc-editor.org/info/rfc1928.[RFC4033]Arends, R., Austein, R., Larson, M., Massey, D., and S. Rose, "DNS Security Introduction and Requirements", RFC 4033, DOI 10.17487/RFC4033, March 2005,https://www.rfc-editor.org/info/rfc4033.[RFC6066]Eastlake 3rd, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, DOI 10.17487/RFC6066, January 2011,https://www.rfc-editor.org/info/rfc6066.[RFC7363]Maenpaa, J. and G. Camarillo, "Self-Tuning Distributed Hash Table (DHT) for REsource LOcation And Discovery (RELOAD)", RFC 7363, DOI 10.17487/RFC7363, September 2014,https://www.rfc-editor.org/info/rfc7363.[RFC8324]Klensin, J., "DNS Privacy, Authorization, Special Uses, Encoding, Characters, Matching, and Root Structure: Time for Another Look?", RFC 8324, DOI 10.17487/RFC8324, February 2018,https://www.rfc-editor.org/info/rfc8324.[RFC8806]Kumari, W. and P. Hoffman, "Running a Root Server Local to a Resolver", RFC 8806, DOI 10.17487/RFC8806, June 2020,https://www.rfc-editor.org/info/rfc8806.[RFC6761]Cheshire, S. and M. Krochmal, "Special-Use Domain Names", RFC 6761, DOI 10.17487/RFC6761, February 2013,https://www.rfc-editor.org/info/rfc6761.[RFC8244]Lemon, T., Droms, R., and W. Kumari, "Special-Use Domain Names Problem Statement", RFC 8244, DOI 10.17487/RFC8244, October 2017,https://www.rfc-editor.org/info/rfc8244.[RFC9476]Kumari, W. and P. Hoffman, "The .alt Special-Use Top-Level Domain", RFC 9476, DOI 10.17487/RFC9476, September 2023,https://www.rfc-editor.org/info/rfc9476.[TorRendSpec]Tor Project, "Tor Rendezvous Specification - Version 3", commit b345ca0, June 2023,https://github.com/torproject/torspec/blob/main/rend-spec-v3.txt.[Tor224]Goulet, D., Kadianakis, G., and N. Mathewson, "Next-Generation Hidden Services in Tor", Appendix A.2 ("Tor's key derivation scheme"), November 2013,https://gitweb.torproject.org/torspec.git/tree/proposals/224-rend-spec-ng.txt#n2135.[SDSI]Rivest, R. L. and B. Lampson, "SDSI - A Simple Distributed Security Infrastructure", October 1996,https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=3837e0206bf73e5e8f0ba6db767a2f714ea7c367.[Kademlia]Maymounkov, P. and D. Maziรจres, "Kademlia: A Peer-to-peer Information System Based on the XOR Metric", DOI 10.1007/3-540-45748-8_5, 2002,https://css.csail.mit.edu/6.824/2014/papers/kademlia.pdf.[ed25519]Bernstein, D. J., Duif, N., Lange, T., Schwabe, P., and B-Y. Yang, "High-speed high-security signatures", DOI 10.1007/s13389-012-0027-1, 2011,https://ed25519.cr.yp.to/ed25519-20110926.pdf.[GNS]Wachs, M., Schanzenbach, M., and C. Grothoff, "A Censorship-Resistant, Privacy-Enhancing and Fully Decentralized Name System", 13th International Conference on Cryptology and Network Security (CANS), DOI 10.13140/2.1.4642.3044, October 2014,https://sci-hub.st/10.1007/978-3-319-12280-9_9.[R5N]Evans, N. S. and C. Grothoff, "R5N: Randomized Recursive Routing for Restricted-Route Networks", 5th International Conference on Network and System Security (NSS), DOI 10.1109/ICNSS.2011.6060022, September 2011,https://sci-hub.st/10.1109/ICNSS.2011.6060022.[SecureNS]Grothoff, C., Wachs, M., Ermert, M., and J. Appelbaum, "Toward secure name resolution on the Internet", Computers and Security, Volume 77, Issue C, pp. 694-708, DOI 10.1016/j.cose.2018.01.018, August 2018,https://sci-hub.st/https://doi.org/10.1016/j.cose.2018.01.018.[GNUnetGNS]GNUnet e.V., "gnunet.git - GNUnet core repository", 2023,https://git.gnunet.org/gnunet.git.[Ascension]GNUnet e.V., "ascension.git - DNS zones to GNS migrating using incremental zone transfer (AXFR/IXFR)", 2023,https://git.gnunet.org/ascension.git.[GNUnet]GNUnet e.V., "The GNUnet Project (Home Page)", 2023,https://gnunet.org.[reclaim]GNUnet e.V., "re:claimID - Self-sovereign, Decentralised Identity Management and Personal Data Sharing", 2023,https://reclaim.gnunet.org.[GoGNS]Fix, B., "gnunet-go (Go GNS)", commit 5c815ba, July 2023,https://github.com/bfix/gnunet-go/tree/master/src/gnunet/service/gns.[nsswitch]GNU Project, "System Databases and Name Service Switch (Section 29)",https://www.gnu.org/software/libc/manual/html_node/Name-Service-Switch.html.
Appendix A. Usage and Migration ๐
okay so this bit is the "why would anyone actually use this?" tour ๐ it walks through a bunch of specific use cases that might help you get what the protocol is for, like the vibe check before the deep dive โจ
but (important!!) none of the considerations below are normative for GNS in any way ๐ they're just here for context and to show what the designers were going for. it also points you at some migration paths ๐ฆ
A.1. Zone Dissemination โจ
Okay so becoming a zone owner is giving easy mode ๐ . You just generate a zone key and its matching secret key with a GNS implementation. Then you can manage your GNS resource records in a local zone database ๐๏ธ, and a GNS implementation can publish them as defined in Section 6. But for other people to resolve those records, the zone information has to be disseminated first ๐ฃ. You get to decide: keep the zone key and labels for a squad of selected users, or put them out there for the whole public ๐ธ.
Sharing directly with specific people is lowkey the best move, because it can help preserve zone and record privacy and lets you and the user build strong trust relationships ๐ซถ. For example, a bank might send a customer letter with a QR code that holds the bank's GNS zone. The user scans it and boom, they have a strong link to the bank's zone, and with it, for example, the IP address of the online banking web site ๐ฆ.
Most Internet services want to make their zones public in the most efficient way possible โก. Zones with high reputation and trust are likely included in the default suffix-to-zone mappings of implementations, so delegation under those zones can be a viable path to going public ๐. It's conceivable that organizations like ICANN or country-code TLD registrars could also manage GNS zones and offer registration or delegation services ๐.
Following best practices, especially the ones about security and abuse mitigation, is how zone owners and aspiring registrars earn a good reputation and, eventually, trust โจ. That includes, of course, diligent protection of private zone key material ๐. Formalizing those best practices is out of scope for this specification. They should be addressed in a separate document that takes Section 9 of this document into account ๐.
A.2. Start Zone Configuration ๐ท
A user is expected to install a GNS implementation if it isn't already provided through other means, like the operating system or the browser. The implementation will most likely ship with a default Start Zone configuration, which means the user can resolve GNS names ending on a zTLD or ending on any suffix-to-name mapping in that default configuration. At this point, the user may delete or otherwise modify the implementation's default configuration:
- Deleting suffix-to-zone mappings may become necessary if the zone owner behind the mapping has lost the user's trust. For example, this could happen because of lax registration policies that lead to phishing activities. Modifying and adding new mappings are ways to heal the namespace perforation that a deletion would cause, or to simply establish a strong direct trust relationship ๐. However, this requires the user's knowledge of the respective zone keys. That information must be retrieved out of band, as illustrated in Appendix A.1: a bank may send the user a letter with a QR code that contains the GNS zone of the bank. The user scans the QR code and adds a new suffix-to-name mapping using a chosen local name for their bank. Other examples include scanning zone information off a friend's device, from a storefront, or from an advertisement. The level of trust in a zone is contextual and likely varies from user to user. Trust in a zone that comes through a letter from a bank, which may also include a credit card, is certainly different from a zone found on a random advertisement on the street. Still, this trust is immediately tangible to the user and can be reflected in the local naming as well ๐.
- Users that are also clients should facilitate modification of the Start Zone configuration, for example by providing a QR code reader or other import mechanisms ๐. Implementations are ideally built according to best practices and address the applicable points from Section 9. Formalizing those best practices is out of scope for this specification ๐.
A.3. Globally Unique Names and the Web ๐
HTTP virtual hosting and TLS Server Name Indication (SNI) are super common on the Web ๐ป. HTTP clients supply a DNS name in the HTTP "Host"-header or as part of the TLS handshake, respectively. That lets the HTTP server serve the indicated virtual host with a matching TLS certificate. The global uniqueness of DNS names is a prerequisite for those use cases ๐ฆ.
Not all GNS names are globally unique. However, any resource record in GNS can be represented as a concatenation of a GNS label and the zTLD of the zone. It's not very memorable, but this globally unique GNS name can be leveraged to facilitate the same use cases ๐ง. Say the GNS name "www.example.gns.alt" is entered in a GNS-aware HTTP client. First, "www.example.gns.alt" is resolved using GNS, yielding a record set. Then the HTTP client determines the virtual host as follows:
If there is a LEHO record (Section 5.3.1) containing "www.example.com" in the record set, then the HTTP client uses this as the value of the "Host"-header field of the HTTP request:
GET / HTTP/1.1
Host: www.example.com
In the absence of a LEHO record, an additional GNS resolution is required to check whether "www.example.gns.alt" itself points to a zone delegation record, which implies that the record set that was originally resolved is published under the apex label.
If it does, the unique GNS name is simply the zTLD representation of the delegated zone:
GET / HTTP/1.1
Host: 000G0037FH3QTBCK15Y8BCCNRVWPV17ZC7TSGB1C9ZG2TPGHZVFV1GMG3W
On the other hand, if there is no zone delegation record for "www.example.gns.alt", then the unique GNS name is the concatenation of the leftmost label (e.g., "www") and the zTLD representation of the zone:
GET / HTTP/1.1
Host: www.000G0037FH3QTBCK15Y8BCCNRVWPV17ZC7TSGB1C9ZG2TPGHZVFV1GMG3W
Note that this second GNS resolution does not require any additional network operation, as only the local record processing differs, per the exception mentioned in the last sentence of Section 7.3.4 ๐ซถ.
If the HTTP client is a browser, the unique GNS name used for virtual hosting or TLS SNI doesn't necessarily have to be shown to the user ๐. For example, the name in the URL bar may remain "www.example.gns.alt" even if the unique name in the "Host"-header differs.
A.4. Migration Paths ๐
DNS resolution is built into a variety of existing software components, most significantly operating systems and HTTP clients ๐. This section illustrates possible migration paths for both, so legacy applications can resolve GNS names.
One efficient way to facilitate GNS name resolution is via GNS-enabled DNS server implementations ๐ง. Local DNS queries are either rerouted or explicitly configured to be resolved by a "DNS-to-GNS" server that runs locally. This DNS server tries to interpret any incoming query for a name as a GNS resolution request. If no Start Zone can be found for the name and it doesn't end in a zTLD, the server tries to resolve the name in DNS. Otherwise, the name is resolved in GNS. In the latter case, the resulting record set is converted to a DNS answer packet and returned accordingly. An implementation of a DNS-to-GNS server can be found in [GNUnet].
A similar approach is to use operating system extensions such as the NSS [nsswitch] ๐ฃ. It lets the system administrator configure plugins that are used for hostname resolution. A GNS nsswitch plugin can be used in a fashion similar to the DNS-to-GNS server. An implementation of a glibc-compatible nsswitch plugin for GNS can be found in [GNUnet] โจ.
The methods above are usually also effective for HTTP client software. However, HTTP clients are commonly used in combination with TLS, and TLS certificate validation, SNI in particular, requires additional logic in HTTP clients when GNS names are in play (Appendix A.3) ๐ญ. To transparently enable this functionality for migration purposes, a local GNS-aware SOCKS5 proxy [RFC1928] can be configured to resolve domain names. Like the DNS-to-GNS server, the SOCKS5 proxy is capable of resolving both GNS and DNS names. For a TLS connection request with a GNS name, the SOCKS5 proxy can terminate the TLS connection and establish a secure connection against the requested host. To establish that secure connection, the proxy may use LEHO and TLSA records stored in the record set under the GNS name. The proxy must provide a locally trusted certificate for the GNS name to the HTTP client, which usually requires generating and configuring a local trust anchor in the browser ๐. An implementation of this SOCKS5 proxy can be found in [GNUnet].
Appendix B. Example Flows ๐ง
B.1. AAAA Example Resolution ๐
Local Host | Remote
| Storage
|
| +---------+
| / /|
| +---------+ |
+-----------+ (1) +----------+ | | | |
| | | | (4,6) | | Record | |
|Application|----------| Resolver |---------------|->| Storage | |
| |<---------| |<--------------|--| |/
+-----------+ (8) +----------+ (5,7) | +---------+
A |
| |
(2,3) | |
| |
| |
+---------+ |
/ v /| |
+---------+ | |
| | | |
| Start | | |
| Zones | | |
| |/ |
+---------+ |
Figure 24: Example Resolution of an IPv6 Address
- Look up AAAA record for name:
"www.example.gnu.gns.alt". - Determine Start Zone for
"www.example.gnu.gns.alt". - Start Zone: zkey0 - Remainder:
"www.example". - Calculate q0=SHA512(ZKDF(zkey0, "example")) and initiate GET(q0).
- Retrieve and decrypt RRBLOCK consisting of a single PKEY record containing zkey1.
- Calculate q1=SHA512(ZKDF(zkey1, "www")) and initiate GET(q1).
- Retrieve RRBLOCK consisting of a single AAAA record containing the IPv6 address 2001:db8::1.
- Return record set to application.
B.2. REDIRECT Example Resolution โจ
okay so this one is about a REDIRECT record ๐ฆ the resolver starts with a name, finds a redirect along the way, and follows it until it reaches an actual AAAA answer. here's the picture first:
Local Host | Remote
| Storage
|
| +---------+
| / /|
| +---------+ |
+-----------+ (1) +----------+ | | | |
| | | | (4,6,8) | | Record | |
|Application|----------| Resolver |----------------|->| Storage | |
| |<---------| |<---------------|--| |/
+-----------+ (10) +----------+ (5,7,9) | +---------+
A |
| |
(2,3) | |
| |
| |
+---------+ |
/ v /| |
+---------+ | |
| | | |
| Start | | |
| Zones | | |
| |/ |
+---------+ |
Figure 25: Example Resolution of an IPv6 Address with Redirect
here's the step-by-step, bestie ๐
- Look up the AAAA record for the name
"www.example.tld.gns.alt". - Determine the Start Zone for
"www.example.tld.gns.alt". - The Start Zone is
zkey0, and the Remainder is"www.example". - Calculate
q0=SHA512(ZKDF(zkey0, "example"))and initiateGET(q0). - Retrieve and decrypt the RRBLOCK, which holds a single PKEY record containing
zkey1. - Calculate
q1=SHA512(ZKDF(zkey1, "www"))and initiateGET(q1). - Retrieve and decrypt the RRBLOCK, which holds a single REDIRECT record containing
"www2.+". - Calculate
q2=SHA512(ZKDF(zkey1, "www2"))and initiateGET(q2). - Retrieve and decrypt the RRBLOCK, which holds a single AAAA record containing the IPv6 address
2001:db8::1. - Return the record set to the application.
the redirect in step 7 is the plot twist ๐ญ๐ฅ
B.3. GNS2DNS Example Resolution ๐ธ
this one is the DNS handover version. the name lives in GNS, but the actual answer comes from the system DNS resolver ๐ง same vibe, different ending.
Local Host | Remote
| Storage
|
| +---------+
| / /|
| +---------+ |
+-----------+ (1) +----------+ | | | |
| | | | (4) | | Record | |
|Application|----------| Resolver |------------------|->| Storage | |
| |<---------| |<-----------------|--| |/
+-----------+ (8) +----------+ (5) | +---------+
A A |
| | (6,7) |
(2,3) | +----------+ |
| | |
| v |
+---------+ +------------+ |
/ v /| | System DNS | |
+---------+ | | Resolver | |
| | | +------------+ |
| Start | | |
| Zones | | |
| |/ |
+---------+ |
Figure 26: Example Resolution of an IPv6 Address with DNS Handover
the steps, in order ๐
- Look up the AAAA record for the name
"www.example.gnu.gns.alt". - Determine the Start Zone for
"www.example.gnu.gns.alt". - The Start Zone is
zkey0, and the Remainder is"www.example". - Calculate
q0=SHA512(ZKDF(zkey0, "example"))and initiateGET(q0). - Retrieve and decrypt the RRBLOCK, which holds a single GNS2DNS record containing the name
"example.com"and the DNS server IPv4 address192.0.2.1. - Use the system resolver to look up an AAAA record for the DNS name
"www.example.com". - Retrieve a DNS reply consisting of a single AAAA record containing the IPv6 address
2001:db8::1. - Return the record set to the application.
Appendix C. Base32GNS ๐
okay, so encoding turns a byte array into a string of symbols, and decoding turns that string back into bytes. if the input string has any symbols outside the defined set, decoding fails ๐
Table 4 is the boss list. each symbol holds 5 bits. so if you see the symbol "A" or "a" while decoding, it turns into the 5-bit value 10. and when you're encoding, a 5-bit block with the value 18 becomes "J" โจ if the bit length of your byte string isn't a multiple of 5, you pad it with zeroes up to the next multiple.
also, for extra forgiveness when characters get misread, the letter "U" MUST be decoded to the same value as the letter "V" in Base32GNS. ๐
+==============+=================+=================+
| Symbol Value | Decoding Symbol | Encoding Symbol |
+==============+=================+=================+
| 0 | 0 O o | 0 |
+--------------+-----------------+-----------------+
| 1 | 1 I i L l | 1 |
+--------------+-----------------+-----------------+
| 2 | 2 | 2 |
+--------------+-----------------+-----------------+
| 3 | 3 | 3 |
+--------------+-----------------+-----------------+
| 4 | 4 | 4 |
+--------------+-----------------+-----------------+
| 5 | 5 | 5 |
+--------------+-----------------+-----------------+
| 6 | 6 | 6 |
+--------------+-----------------+-----------------+
| 7 | 7 | 7 |
+--------------+-----------------+-----------------+
| 8 | 8 | 8 |
+--------------+-----------------+-----------------+
| 9 | 9 | 9 |
+--------------+-----------------+-----------------+
| 10 | A a | A |
+--------------+-----------------+-----------------+
| 11 | B b | B |
+--------------+-----------------+-----------------+
| 12 | C c | C |
+--------------+-----------------+-----------------+
| 13 | D d | D |
+--------------+-----------------+-----------------+
| 14 | E e | E |
+--------------+-----------------+-----------------+
| 15 | F f | F |
+--------------+-----------------+-----------------+
| 16 | G g | G |
+--------------+-----------------+-----------------+
| 17 | H h | H |
+--------------+-----------------+-----------------+
| 18 | J j | J |
+--------------+-----------------+-----------------+
| 19 | K k | K |
+--------------+-----------------+-----------------+
| 20 | M m | M |
+--------------+-----------------+-----------------+
| 21 | N n | N |
+--------------+-----------------+-----------------+
| 22 | P p | P |
+--------------+-----------------+-----------------+
| 23 | Q q | Q |
+--------------+-----------------+-----------------+
| 24 | R r | R |
+--------------+-----------------+-----------------+
| 25 | S s | S |
+--------------+-----------------+-----------------+
| 26 | T t | T |
+--------------+-----------------+-----------------+
| 27 | V v U u | V |
+--------------+-----------------+-----------------+
| 28 | W w | W |
+--------------+-----------------+-----------------+
| 29 | X x | X |
+--------------+-----------------+-----------------+
| 30 | Y y | Y |
+--------------+-----------------+-----------------+
| 31 | Z z | Z |
+--------------+-----------------+-----------------+
Table 4: The Base32GNS Alphabet, Including the Additional Encoding Symbol "U"
Appendix D. Test Vectors ๐ง
these test vectors are your conformance checklist, bestie โ implementations can use them to check themselves. unless it says otherwise, the vectors are hexadecimal byte arrays.
D.1. Base32GNS Encoding/Decoding
these are the Base32GNS test vectors for the encoding used by zTLDs. the input strings get encoded without the zero terminator ๐
Base32GNS-Encode:
Input string: "Hello World"
Output string: "91JPRV3F41BPYWKCCG"
Input bytes: 474e55204e616d652053797374656d
Output string: "8X75A82EC5PPA82KF5SQ8SBD"
Base32GNS-Decode:
Input string: "91JPRV3F41BPYWKCCG"
Output string: "Hello World"
Input string: "91JPRU3F41BPYWKCCG"
Output string: "Hello World"
D.2. Record Sets ๐
these vectors cover record sets with a bunch of record types and flags, for both PKEY and EDKEY zones. they even include labels with UTF-8 characters, so the internationalized labels get a moment to shine โจ
(1) PKEY zone with ASCII label and one delegation record
Zone private key (d, big-endian):
50 d7 b6 52 a4 ef ea df
f3 73 96 90 97 85 e5 95
21 71 a0 21 78 c8 e7 d4
50 fa 90 79 25 fa fd 98
Zone identifier (ztype|zkey):
00 01 00 00 67 7c 47 7d
2d 93 09 7c 85 b1 95 c6
f9 6d 84 ff 61 f5 98 2c
2c 4f e0 2d 5a 11 fe df
b0 c2 90 1f
zTLD:
000G0037FH3QTBCK15Y8BCCNRVWPV17ZC7TSGB1C9ZG2TPGHZVFV1GMG3W
Label:
74 65 73 74 64 65 6c 65
67 61 74 69 6f 6e
Number of records (integer): 1
Record #0 := (
EXPIRATION: 8143584694000000 us
00 1c ee 8c 10 e2 59 80
DATA_SIZE:
00 20
TYPE:
00 01 00 00
FLAGS: 00 01
DATA:
21 e3 b3 0f f9 3b c6 d3
5a c8 c6 e0 e1 3a fd ff
79 4c b7 b4 4b bb c7 48
d2 59 d0 a0 28 4d be 84
)
RDATA:
00 1c ee 8c 10 e2 59 80
00 20 00 01 00 01 00 00
21 e3 b3 0f f9 3b c6 d3
5a c8 c6 e0 e1 3a fd ff
79 4c b7 b4 4b bb c7 48
d2 59 d0 a0 28 4d be 84
Okay bestie, the hex is about to get very intense ๐ฆ Buckle up and let the bytes cook ๐
Encryption NONCE|EXPIRATION|BLOCK COUNTER:
e9 0a 00 61 00 1c ee 8c
10 e2 59 80 00 00 00 01
Encryption key (K):
86 4e 71 38 ea e7 fd 91
a3 01 36 89 9c 13 2b 23
ac eb db 2c ef 43 cb 19
f6 bf 55 b6 7d b9 b3 b3
Storage key (q):
4a dc 67 c5 ec ee 9f 76
98 6a bd 71 c2 22 4a 3d
ce 2e 91 70 26 c9 a0 9d
fd 44 ce f3 d2 0f 55 a2
73 32 72 5a 6c 8a fb bb
b0 f7 ec 9a f1 cc 42 64
12 99 40 6b 04 fd 9b 5b
57 91 f8 6c 4b 08 d5 f4
ZKDF(zkey, label):
18 2b b6 36 ed a7 9f 79
57 11 bc 27 08 ad bb 24
2a 60 44 6a d3 c3 08 03
12 1d 03 d3 48 b7 ce b6
Derived private key (d', big-endian):
0a 4c 5e 0f 00 63 df ce
db c8 c7 f2 b2 2c 03 0c
86 28 b2 c2 cb ac 9f a7
29 aa e6 1f 89 db 3e 9c
BDATA:
0c 1e da 5c c0 94 a1 c7
a8 88 64 9d 25 fa ee bd
60 da e6 07 3d 57 d8 ae
8d 45 5f 4f 13 92 c0 74
e2 6a c6 69 bd ee c2 34
62 b9 62 95 2c c6 e9 eb
RRBLOCK:
00 00 00 a0 00 01 00 00
18 2b b6 36 ed a7 9f 79
57 11 bc 27 08 ad bb 24
2a 60 44 6a d3 c3 08 03
12 1d 03 d3 48 b7 ce b6
0a d1 0b c1 3b 40 3b 5b
25 61 26 b2 14 5a 6f 60
c5 14 f9 51 ff a7 66 f7
a3 fd 4b ac 4a 4e 19 90
05 5c b8 7e 8d 1b fd 19
aa 09 a4 29 f7 29 e9 f5
c6 ee c2 47 0a ce e2 22
07 59 e9 e3 6c 88 6f 35
00 1c ee 8c 10 e2 59 80
0c 1e da 5c c0 94 a1 c7
a8 88 64 9d 25 fa ee bd
60 da e6 07 3d 57 d8 ae
8d 45 5f 4f 13 92 c0 74
e2 6a c6 69 bd ee c2 34
62 b9 62 95 2c c6 e9 eb
(2) PKEY zone with UTF-8 label and three records ๐
Zone private key (d, big-endian):
50 d7 b6 52 a4 ef ea df
f3 73 96 90 97 85 e5 95
21 71 a0 21 78 c8 e7 d4
50 fa 90 79 25 fa fd 98
Zone identifier (ztype|zkey):
00 01 00 00 67 7c 47 7d
2d 93 09 7c 85 b1 95 c6
f9 6d 84 ff 61 f5 98 2c
2c 4f e0 2d 5a 11 fe df
b0 c2 90 1f
zTLD:
000G0037FH3QTBCK15Y8BCCNRVWPV17ZC7TSGB1C9ZG2TPGHZVFV1GMG3W
Label:
e5 a4 a9 e4 b8 8b e7 84
a1 e6 95 b5
Number of records (integer): 3
Record #0 := (
EXPIRATION: 8143584694000000 us
00 1c ee 8c 10 e2 59 80
DATA_SIZE:
00 10
TYPE:
00 00 00 1c
FLAGS: 00 00
DATA:
00 00 00 00 00 00 00 00
00 00 00 00 de ad be ef
)
Record #1 := (
EXPIRATION: 17999736901000000 us
00 3f f2 aa 54 08 db 40
DATA_SIZE:
00 06
TYPE:
00 01 00 01
FLAGS: 00 00
DATA:
e6 84 9b e7 a7 b0
)
Record #2 := (
EXPIRATION: 11464693629000000 us
00 28 bb 13 ff 37 19 40
DATA_SIZE:
00 0b
TYPE:
00 00 00 10
FLAGS: 00 04
DATA:
48 65 6c 6c 6f 20 57 6f
72 6c 64
)
RDATA:
00 1c ee 8c 10 e2 59 80
00 10 00 00 00 00 00 1c
00 00 00 00 00 00 00 00
00 00 00 00 de ad be ef
00 3f f2 aa 54 08 db 40
00 06 00 00 00 01 00 01
e6 84 9b e7 a7 b0 00 28
bb 13 ff 37 19 40 00 0b
00 04 00 00 00 10 48 65
6c 6c 6f 20 57 6f 72 6c
64 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
Encryption NONCE|EXPIRATION|BLOCK COUNTER:
ee 96 33 c1 00 1c ee 8c
10 e2 59 80 00 00 00 01
Encryption key (K):
fb 3a b5 de 23 bd da e1
99 7a af 7b 92 c2 d2 71
51 40 8b 77 af 7a 41 ac
79 05 7c 4d f5 38 3d 01
Storage key (q):
af f0 ad 6a 44 09 73 68
42 9a c4 76 df a1 f3 4b
ee 4c 36 e7 47 6d 07 aa
64 63 ff 20 91 5b 10 05
c0 99 1d ef 91 fc 3e 10
90 9f 87 02 c0 be 40 43
67 78 c7 11 f2 ca 47 d5
5c f0 b5 4d 23 5d a9 77
ZKDF(zkey, label):
a5 12 96 df 75 7e e2 75
ca 11 8d 4f 07 fa 7a ae
55 08 bc f5 12 aa 41 12
14 29 d4 a0 de 9d 05 7e
Derived private key (d', big-endian):
0a be 56 d6 80 68 ab 40
e1 44 79 0c de 9a cf 4d
78 7f 2d 3c 63 b8 53 05
74 6e 68 03 32 15 f2 ab
BDATA:
d8 c2 8d 2f d6 96 7d 1a
b7 22 53 f2 10 98 b8 14
a4 10 be 1f 59 98 de 03
f5 8f 7e 7c db 7f 08 a6
16 51 be 4d 0b 6f 8a 61
df 15 30 44 0b d7 47 dc
f0 d7 10 4f 6b 8d 24 c2
ac 9b c1 3d 9c 6f e8 29
05 25 d2 a6 d0 f8 84 42
67 a1 57 0e 8e 29 4d c9
3a 31 9f cf c0 3e a2 70
17 d6 fd a3 47 b4 a7 94
97 d7 f6 b1 42 2d 4e dd
82 1c 19 93 4e 96 c1 aa
87 76 57 25 d4 94 c7 64
b1 55 dc 6d 13 26 91 74
RRBLOCK:
00 00 00 f0 00 01 00 00
a5 12 96 df 75 7e e2 75
ca 11 8d 4f 07 fa 7a ae
55 08 bc f5 12 aa 41 12
14 29 d4 a0 de 9d 05 7e
08 5b d6 5f d4 85 10 51
ba ce 2a 45 2a fc 8a 7e
4f 6b 2c 1f 74 f0 20 35
d9 64 1a cd ba a4 66 e0
00 ce d6 f2 d2 3b 63 1c
8e 8a 0b 38 e2 ba e7 9a
22 ca d8 1d 4c 50 d2 25
35 8e bc 17 ac 0f 89 9e
00 1c ee 8c 10 e2 59 80
d8 c2 8d 2f d6 96 7d 1a
b7 22 53 f2 10 98 b8 14
a4 10 be 1f 59 98 de 03
f5 8f 7e 7c db 7f 08 a6
16 51 be 4d 0b 6f 8a 61
df 15 30 44 0b d7 47 dc
f0 d7 10 4f 6b 8d 24 c2
ac 9b c1 3d 9c 6f e8 29
05 25 d2 a6 d0 f8 84 42
67 a1 57 0e 8e 29 4d c9
3a 31 9f cf c0 3e a2 70
17 d6 fd a3 47 b4 a7 94
97 d7 f6 b1 42 2d 4e dd
82 1c 19 93 4e 96 c1 aa
87 76 57 25 d4 94 c7 64
b1 55 dc 6d 13 26 91 74
(3) EDKEY zone with ASCII label and one delegation record ๐ง
Zone private key (d):
5a f7 02 0e e1 91 60 32
88 32 35 2b bc 6a 68 a8
d7 1a 7c be 1b 92 99 69
a7 c6 6d 41 5a 0d 8f 65
Zone identifier (ztype|zkey):
00 01 00 14 3c f4 b9 24
03 20 22 f0 dc 50 58 14
53 b8 5d 93 b0 47 b6 3d
44 6c 58 45 cb 48 44 5d
db 96 68 8f
zTLD:
000G051WYJWJ80S04BRDRM2R2H9VGQCKP13VCFA4DHC4BJT88HEXQ5K8HW
Label:
74 65 73 74 64 65 6c 65
67 61 74 69 6f 6e
Number of records (integer): 1
Record #0 := (
EXPIRATION: 8143584694000000 us
00 1c ee 8c 10 e2 59 80
DATA_SIZE:
00 20
TYPE:
00 01 00 00
FLAGS: 00 01
DATA:
21 e3 b3 0f f9 3b c6 d3
5a c8 c6 e0 e1 3a fd ff
79 4c b7 b4 4b bb c7 48
d2 59 d0 a0 28 4d be 84
)
RDATA:
00 1c ee 8c 10 e2 59 80
00 20 00 01 00 01 00 00
21 e3 b3 0f f9 3b c6 d3
5a c8 c6 e0 e1 3a fd ff
79 4c b7 b4 4b bb c7 48
d2 59 d0 a0 28 4d be 84
Encryption NONCE|EXPIRATION:
98 13 2e a8 68 59 d3 5c
88 bf d3 17 fa 99 1b cb
00 1c ee 8c 10 e2 59 80
Encryption key (K):
85 c4 29 a9 56 7a a6 33
41 1a 96 91 e9 09 4c 45
28 16 72 be 58 60 34 aa
e4 a2 a2 cc 71 61 59 e2
Storage key (q):
ab aa ba c0 e1 24 94 59
75 98 83 95 aa c0 24 1e
55 59 c4 1c 40 74 e2 55
7b 9f e6 d1 54 b6 14 fb
cd d4 7f c7 f5 1d 78 6d
c2 e0 b1 ec e7 60 37 c0
a1 57 8c 38 4e c6 1d 44
56 36 a9 4e 88 03 29 e9
ZKDF(zkey, label):
9b f2 33 19 8c 6d 53 bb
db ac 49 5c ab d9 10 49
a6 84 af 3f 40 51 ba ca
b0 dc f2 1c 8c f2 7a 1a
nonce := SHA-256(dh[32..63] || h):
14 f2 c0 6b ed c3 aa 2d
f0 71 13 9c 50 39 34 f3
4b fa 63 11 a8 52 f2 11
f7 3a df 2e 07 61 ec 35
Derived private key (d', big-endian):
3b 1b 29 d4 23 0b 10 a8
ec 4d a3 c8 6e db 88 ea
cd 54 08 5c 1d db 63 f7
a9 d7 3f 7c cb 2f c3 98
BDATA:
57 7c c6 c9 5a 14 e7 04
09 f2 0b 01 67 e6 36 d0
10 80 7c 4f 00 37 2d 69
8c 82 6b d9 2b c2 2b d6
bb 45 e5 27 7c 01 88 1d
6a 43 60 68 e4 dd f1 c6
b7 d1 41 6f af a6 69 7c
25 ed d9 ea e9 91 67 c3
RRBLOCK:
00 00 00 b0 00 01 00 14
9b f2 33 19 8c 6d 53 bb
db ac 49 5c ab d9 10 49
a6 84 af 3f 40 51 ba ca
b0 dc f2 1c 8c f2 7a 1a
9f 56 a8 86 ea 73 9d 59
17 50 8f 9b 75 56 39 f3
a9 ac fa ed ed ca 7f bf
a7 94 b1 92 e0 8b f9 ed
4c 7e c8 59 4c 9f 7b 4e
19 77 4f f8 38 ec 38 7a
8f 34 23 da ac 44 9f 59
db 4e 83 94 3f 90 72 00
00 1c ee 8c 10 e2 59 80
57 7c c6 c9 5a 14 e7 04
09 f2 0b 01 67 e6 36 d0
10 80 7c 4f 00 37 2d 69
8c 82 6b d9 2b c2 2b d6
bb 45 e5 27 7c 01 88 1d
6a 43 60 68 e4 dd f1 c6
b7 d1 41 6f af a6 69 7c
25 ed d9 ea e9 91 67 c3
(4) EDKEY zone with UTF-8 label and three records ๐
Zone private key (d):
5a f7 02 0e e1 91 60 32
88 32 35 2b bc 6a 68 a8
d7 1a 7c be 1b 92 99 69
a7 c6 6d 41 5a 0d 8f 65
Zone identifier (ztype|zkey):
00 01 00 14 3c f4 b9 24
03 20 22 f0 dc 50 58 14
53 b8 5d 93 b0 47 b6 3d
44 6c 58 45 cb 48 44 5d
db 96 68 8f
zTLD:
000G051WYJWJ80S04BRDRM2R2H9VGQCKP13VCFA4DHC4BJT88HEXQ5K8HW
Label:
e5 a4 a9 e4 b8 8b e7 84
a1 e6 95 b5
Number of records (integer): 3
Record #0 := (
EXPIRATION: 8143584694000000 us
00 1c ee 8c 10 e2 59 80
DATA_SIZE:
00 10
TYPE:
00 00 00 1c
FLAGS: 00 00
DATA:
00 00 00 00 00 00 00 00
00 00 00 00 de ad be ef
)
Record #1 := (
EXPIRATION: 17999736901000000 us
00 3f f2 aa 54 08 db 40
DATA_SIZE:
00 06
TYPE:
00 01 00 01
FLAGS: 00 00
DATA:
e6 84 9b e7 a7 b0
)
Record #2 := (
EXPIRATION: 11464693629000000 us
00 28 bb 13 ff 37 19 40
DATA_SIZE:
00 0b
TYPE:
00 00 00 10
FLAGS: 00 04
DATA:
48 65 6c 6c 6f 20 57 6f
72 6c 64
)
RDATA:
00 1c ee 8c 10 e2 59 80
00 10 00 00 00 00 00 1c
00 00 00 00 00 00 00 00
00 00 00 00 de ad be ef
00 3f f2 aa 54 08 db 40
00 06 00 00 00 01 00 01
e6 84 9b e7 a7 b0 00 28
bb 13 ff 37 19 40 00 0b
00 04 00 00 00 10 48 65
6c 6c 6f 20 57 6f 72 6c
64 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
Encryption NONCE|EXPIRATION:
bb 0d 3f 0f bd 22 42 77
50 da 5d 69 12 16 e6 c9
00 1c ee 8c 10 e2 59 80
Encryption key (K):
3d f8 05 bd 66 87 aa 14
20 96 28 c2 44 b1 11 91
88 c3 92 56 37 a4 1e 5d
76 49 6c 29 45 dc 37 7b
Storage key (q):
ba f8 21 77 ee c0 81 e0
74 a7 da 47 ff c6 48 77
58 fb 0d f0 1a 6c 7f bb
52 fc 8a 31 be f0 29 af
74 aa 0d c1 5a b8 e2 fa
7a 54 b4 f5 f6 37 f6 15
8f a7 f0 3c 3f ce be 78
d3 f9 d6 40 aa c0 d1 ed
ZKDF(zkey, label):
74 f9 00 68 f1 67 69 53
52 a8 a6 c2 eb 98 48 98
c5 3a cc a0 98 04 70 c6
c8 12 64 cb dd 78 ad 11
nonce := SHA-256(dh[32..63] || h):
f8 6a b5 33 8a 74 d7 a1
d2 77 ea 11 ff 95 cb e8
3a cf d3 97 3b b4 ab ca
0a 1b 60 62 c3 7a b3 9c
Derived private key (d', big-endian):
17 c0 68 a6 c3 f7 20 de
0e 1b 69 ff 3f 53 e0 5d
3f e5 c5 b0 51 25 7a 89
a6 3c 1a d3 5a c4 35 58
BDATA:
4e b3 5a 50 d4 0f e1 a4
29 c7 f4 b2 67 a0 59 de
4e 2c 8a 89 a5 ed 53 d3
d4 92 58 59 d2 94 9f 7f
30 d8 a2 0c aa 96 f8 81
45 05 2d 1c da 04 12 49
8f f2 5f f2 81 6e f0 ce
61 fe 69 9b fa c7 2c 15
dc 83 0e a9 b0 36 17 1c
cf ca bb dd a8 de 3c 86
ed e2 95 70 d0 17 4b 82
82 09 48 a9 28 b7 f0 0e
fb 40 1c 10 fe 80 bb bb
02 76 33 1b f7 f5 1b 8d
74 57 9c 14 14 f2 2d 50
1a d2 5a e2 49 f5 bb f2
a6 c3 72 59 d1 75 e4 40
b2 94 39 c6 05 19 cb b1
RRBLOCK:
00 00 01 00 00 01 00 14
74 f9 00 68 f1 67 69 53
52 a8 a6 c2 eb 98 48 98
c5 3a cc a0 98 04 70 c6
c8 12 64 cb dd 78 ad 11
75 6d 2c 15 7a d2 ea 4f
c0 b1 b9 1c 08 03 79 44
61 d3 de f2 0d d1 63 6c
fe dc 03 89 c5 49 d1 43
6c c3 5b 4e 1b f8 89 5a
64 6b d9 a6 f4 6b 83 48
1d 9c 0e 91 d4 e1 be bb
6a 83 52 6f b7 25 2a 06
00 1c ee 8c 10 e2 59 80
4e b3 5a 50 d4 0f e1 a4
29 c7 f4 b2 67 a0 59 de
4e 2c 8a 89 a5 ed 53 d3
d4 92 58 59 d2 94 9f 7f
30 d8 a2 0c aa 96 f8 81
45 05 2d 1c da 04 12 49
8f f2 5f f2 81 6e f0 ce
61 fe 69 9b fa c7 2c 15
dc 83 0e a9 b0 36 17 1c
cf ca bb dd a8 de 3c 86
ed e2 95 70 d0 17 4b 82
82 09 48 a9 28 b7 f0 0e
fb 40 1c 10 fe 80 bb bb
02 76 33 1b f7 f5 1b 8d
74 57 9c 14 14 f2 2d 50
1a d2 5a e2 49 f5 bb f2
a6 c3 72 59 d1 75 e4 40
b2 94 39 c6 05 19 cb b1
D.3. Zone Revocation ๐ฆ
okay so here's an example revocation for a PKEY zone ๐ โจ
Zone private key (d, big-endian):
6f ea 32 c0 5a f5 8b fa
97 95 53 d1 88 60 5f d5
7d 8b f9 cc 26 3b 78 d5
f7 47 8c 07 b9 98 ed 70
Zone identifier (ztype|zkey):
00 01 00 00 2c a2 23 e8
79 ec c4 bb de b5 da 17
31 92 81 d6 3b 2e 3b 69
55 f1 c3 77 5c 80 4a 98
d5 f8 dd aa
zTLD: 000G001CM8HYGYFCRJXXXDET2WRS50EP7CQ3PTANY71QEQ409ACDBY6XN8 ๐
Difficulty (5 base difficulty + 2 epochs): 7
Signed message:
00 00 00 34 00 00 00 03
00 05 ff 1c 56 e4 b2 68
00 01 00 00 2c a2 23 e8
79 ec c4 bb de b5 da 17
31 92 81 d6 3b 2e 3b 69
55 f1 c3 77 5c 80 4a 98
d5 f8 dd aa
Proof:
00 05 ff 1c 56 e4 b2 68
00 00 39 5d 18 27 c0 00
38 0b 54 aa 70 16 ac a2
38 0b 54 aa 70 16 ad 62
38 0b 54 aa 70 16 af 3e
38 0b 54 aa 70 16 af 93
38 0b 54 aa 70 16 b0 bf
38 0b 54 aa 70 16 b0 ee
38 0b 54 aa 70 16 b1 c9
38 0b 54 aa 70 16 b1 e5
38 0b 54 aa 70 16 b2 78
38 0b 54 aa 70 16 b2 b2
38 0b 54 aa 70 16 b2 d6
38 0b 54 aa 70 16 b2 e4
38 0b 54 aa 70 16 b3 2c
38 0b 54 aa 70 16 b3 5a
38 0b 54 aa 70 16 b3 9d
38 0b 54 aa 70 16 b3 c0
38 0b 54 aa 70 16 b3 dd
38 0b 54 aa 70 16 b3 f4
38 0b 54 aa 70 16 b4 42
38 0b 54 aa 70 16 b4 76
38 0b 54 aa 70 16 b4 8c
38 0b 54 aa 70 16 b4 a4
38 0b 54 aa 70 16 b4 c9
38 0b 54 aa 70 16 b4 f0
38 0b 54 aa 70 16 b4 f7
38 0b 54 aa 70 16 b5 79
38 0b 54 aa 70 16 b6 34
38 0b 54 aa 70 16 b6 8e
38 0b 54 aa 70 16 b7 b4
38 0b 54 aa 70 16 b8 7e
38 0b 54 aa 70 16 b8 f8
38 0b 54 aa 70 16 b9 2a
00 01 00 00 2c a2 23 e8
79 ec c4 bb de b5 da 17
31 92 81 d6 3b 2e 3b 69
55 f1 c3 77 5c 80 4a 98
d5 f8 dd aa 08 ca ff de
3c 6d f1 45 f7 e0 79 81
15 37 b2 b0 42 2d 5e 1f
b2 01 97 81 ec a2 61 d1
f9 d8 ea 81 0a bc 2f 33
47 7f 04 e3 64 81 11 be
71 c2 48 82 1a d6 04 f4
94 e7 4d 0b f5 11 d2 c1
62 77 2e 81
and now the EDKEY one, same energy but a different zone type ๐โจ
Zone private key (d):
5a f7 02 0e e1 91 60 32
88 32 35 2b bc 6a 68 a8
d7 1a 7c be 1b 92 99 69
a7 c6 6d 41 5a 0d 8f 65
Zone identifier (ztype|zkey):
00 01 00 14 3c f4 b9 24
03 20 22 f0 dc 50 58 14
53 b8 5d 93 b0 47 b6 3d
44 6c 58 45 cb 48 44 5d
db 96 68 8f
zTLD: 000G051WYJWJ80S04BRDRM2R2H9VGQCKP13VCFA4DHC4BJT88HEXQ5K8HW ๐ง
Difficulty (5 base difficulty + 2 epochs): 7
Signed message:
00 00 00 34 00 00 00 03
00 05 ff 1c 57 35 42 bd
00 01 00 14 3c f4 b9 24
03 20 22 f0 dc 50 58 14
53 b8 5d 93 b0 47 b6 3d
44 6c 58 45 cb 48 44 5d
db 96 68 8f
Proof:
00 05 ff 1c 57 35 42 bd
00 00 39 5d 18 27 c0 00
58 4c 93 3c b0 99 2a 08
58 4c 93 3c b0 99 2d f7
58 4c 93 3c b0 99 2e 21
58 4c 93 3c b0 99 2e 2a
58 4c 93 3c b0 99 2e 53
58 4c 93 3c b0 99 2e 8e
58 4c 93 3c b0 99 2f 13
58 4c 93 3c b0 99 2f 2d
58 4c 93 3c b0 99 2f 3c
58 4c 93 3c b0 99 2f 41
58 4c 93 3c b0 99 2f fd
58 4c 93 3c b0 99 30 33
58 4c 93 3c b0 99 30 82
58 4c 93 3c b0 99 30 a2
58 4c 93 3c b0 99 30 e1
58 4c 93 3c b0 99 31 ce
58 4c 93 3c b0 99 31 de
58 4c 93 3c b0 99 32 12
58 4c 93 3c b0 99 32 4e
58 4c 93 3c b0 99 32 9f
58 4c 93 3c b0 99 33 31
58 4c 93 3c b0 99 33 87
58 4c 93 3c b0 99 33 8c
58 4c 93 3c b0 99 33 e5
58 4c 93 3c b0 99 33 f3
58 4c 93 3c b0 99 34 26
58 4c 93 3c b0 99 34 30
58 4c 93 3c b0 99 34 68
58 4c 93 3c b0 99 34 88
58 4c 93 3c b0 99 34 8a
58 4c 93 3c b0 99 35 4c
58 4c 93 3c b0 99 35 bd
00 01 00 14 3c f4 b9 24
03 20 22 f0 dc 50 58 14
53 b8 5d 93 b0 47 b6 3d
44 6c 58 45 cb 48 44 5d
db 96 68 8f 04 ae 26 f7
63 56 5a b7 aa ab 01 71
72 4f 3c a8 bc c5 1a 98
b7 d4 c9 2e a3 3c d9 34
4c a8 b6 3e 04 53 3a bf
1a 3c 05 49 16 b3 68 2c
5c a8 cb 4d d0 f8 4c 3b
77 48 7a ac 6e ce 38 48
0b a9 d5 00
Acknowledgements
the authors wanna thank everyone who reviewed this ๐ซถ for real, the reviews were so detailed and so smart. special shoutouts to D. J. Bernstein, S. Bortzmeyer, A. Farrel, E. Lear, and R. Salz for their insightful and detailed technical reviews ๐ฅ. thank you also to J. Yao and J. Klensin for the internationalization reviews ๐ธ. thanks to Dr. J. Appelbaum for suggesting the name "GNU Name System" ๐, and to Dr. Richard Stallman for approving its use ๐. T. Lange and M. Wachs get a big thank you for their earlier contributions to the design and implementation of GNS โจ. and finally, NLnet and NGI DISCOVERY for funding work on the GNU Name System, you're literally the best ๐ฆ
Authors' Addresses
Martin Schanzenbach ๐ Fraunhofer AISEC Lichtenbergstrasse 11 85748 Garching Germany Email: martin.schanzenbach@aisec.fraunhofer.de
Christian Grothoff ๐ง Berner Fachhochschule Hoeheweg 80 CH-2501 Biel/Bienne Switzerland Email: christian.grothoff@bfh.ch
Bernd Fix ๐ GNUnet e.V. Boltzmannstrasse 3 85748 Garching Germany Email: fix@gnunet.org
๐ฆ where this page comes from
- ietf: rfc9498 2023-11
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms