VeilNet

Identity

An anchor's identity is its own post-quantum key, and its AnchorID and addresses all come from that key.

The Identity Key

An anchor's identity is an ML-DSA key pair, ML-DSA-87 in the default cipher suite. No registry, naming authority or certificate authority stands above it. Only the holder of the private key can claim the identity.

The key pair is generated from a seed. Anyone who holds the seed can recreate the key and act as the anchor, so protect the seed like any private key.

The identity key has three properties:

  • It never rotates. A new key gives a new AnchorID, and the realm treats it as a new anchor.
  • It cannot be revoked. To remove an anchor, let its credential lapse or block it. See Revocation.
  • It grants nothing on its own. Anyone can generate a key. What an anchor may do comes from the credential chain that names it, never from the key.

The AnchorID

Fig. 01 — The AnchorID and addresses, derived from one seed
SEED · 32 BYTES7f3a 91c0 5d2e 08b4 … 6a1f 2be8 c901PRIVATE KEYsigns, and stays secretPUBLIC KEY · ML-DSA-87the identity itselfANCHORID · A SHA3-256 HASH OF THE PUBLIC KEYanchor6btpa3gn6w4stipba4hekzho7caw6srfyy5puvbz7mfanaiept5a58 CHARACTERS · CASE-INSENSITIVE · 32 BYTESMAC ADDRESSits address on the segmentOVERLAY IPV6 ADDRESSfd80:c4b9:99ae:4411:c531:fd4f:754f:f08a/48 FROM THE ROOT OF THE TREEFROM THE ANCHORID

The /48 prefix comes from the root of the tree, so the whole tree shares one prefix. The rest of the IPv6 address, and the MAC address, come from the anchor's own key. The key shown uses the default suite.

The AnchorID is the anchor's name on the network. It is a SHA3-256 hash of the public key and the cipher suite. The hash is never shortened, so an attacker cannot find a second key with the same AnchorID.

In text, an AnchorID is anchor followed by lowercase base32, 58 characters in all. AnchorIDs are case-insensitive, so they survive DNS labels, file names and tools that change case. A damaged AnchorID is refused, never read as a different anchor.

anchor6btpa3gn6w4stipba4hekzho7caw6srfyy5puvbz7mfanaiept5a
  • Realm names look similar. A realm's name comes from its root key in the same way, and starts with realm. A realm name is never accepted where an AnchorID is expected, or the other way round.
  • The short form is for reading only. Logs and tables show the first ten characters. Ten characters are enough to recognise an anchor, but not to trust it, so commands that name an anchor need all 58 characters.

Derived addresses

Every anchor's addresses come from its identity, so nobody needs to draw up an address plan. The overlay uses one IPv6 /48 prefix in the unique-local range, fd00::/8, which is never routed on the internet. The prefix comes from the root of the tree, which every member pins.

An anchor's IPv6 address inside the prefix comes from its AnchorID, and its MAC address comes from its identity. Every member can work out every other member's addresses before either anchor starts. See Overlay Addresses.

Signing

An anchor uses its identity key to sign the statements it makes about itself:

  • its knock, the first message it sends when it dials a peer
  • its proof of membership after each handshake
  • its route offers
  • its notice that it is leaving
  • its taint record

If its credential carries a power, the anchor also signs orders, and records that every member of the realm stores.

Every signature uses fresh randomness and names its purpose. A signature made for one purpose therefore cannot be replayed as another.

Key Storage

A key file holds the seed, not the full private key. The file is therefore small enough for a paper or QR-code backup.

Fig. 02 — What a key file holds
NO PASSPHRASE · 47 BYTESVEILNET7VER1SUITE1ROLE1KDF1SEED32SUM4ROLE · 0x01 ANCHOR, 0x02 REALM ROOTSUM · CATCHES DAMAGE, NOT TAMPERINGWITH A PASSPHRASE · 100 BYTESVEILNET7VER1SUITE1ROLE1KDF1SALT16TIME4MEM4THR1NONCE12SEED, SEALED32TAG16SUM4HEADER · PROTECTED AGAINST TAMPERINGAES-256-GCM UNDER AN ARGON2ID KEY
Swipe to see the full chart

The same format holds either an anchor's identity or a realm's root key, and the role field says which. The checksum catches a damaged file, but does not protect it against tampering. With a passphrase, the encryption also protects the file against tampering.

  • One format for two kinds of key. The file says whether it holds an anchor's identity or a realm's root key. An anchor refuses to start with a realm key, and an identity cannot sign credentials.
  • An optional passphrase. A passphrase encrypts the seed with AES-256-GCM, under a key derived with Argon2id. The file's settings are protected too, so nobody can weaken an existing file.
  • Clear errors. A wrong passphrase fails with identity: wrong passphrase, and never produces a different identity. A damaged or truncated file also fails with its own error.
  • Safe writes. The file is written in one step, with mode 0600.

On a conflux machine

Conflux keeps the machine's seed in its manifest, at /var/lib/conflux/manifest.b64 on Linux. The manifest also holds the pinned root, the credential chain and everything else the anchor needs to start.

Conflux writes the manifest in one step, with mode 0600, in a directory that only root can open. It passes the manifest to the anchor on standard input, never on a command line or in a log.

Inspecting the Identity

To see the machine's AnchorID, run:

$ sudo conflux status

The anchor row shows the full AnchorID, all 58 characters. Use this form in any command that names the machine. sudo conflux peers lists every other member by its ten-character short form, next to its overlay and MAC addresses.

To check that the manifest is protected, run:

$ sudo ls -l /var/lib/conflux/manifest.b64
-rw------- 1 root root … /var/lib/conflux/manifest.b64

If the mode allows more than -rw-------, or the owner is not root, restrict the file to root before you do anything else.