Commit Graph
3760 Commits
Author SHA1 Message Date
Adrien Beraud a06695734d network: require a session for keyed value requests 2026-10-29 23:28:48 -04:00
Adrien Beraud 35aa47029e tests: reject unvalidated transport value requests 2026-10-29 23:28:48 -04:00
Adrien Beraud 4af12a4c2c docs: describe per-peer session recovery 2026-10-29 23:28:48 -04:00
Adrien Beraud 3f77b6b820 network: recover lost sessions per peer 2026-10-29 23:28:48 -04:00
Adrien Beraud 858867dc56 tests: check that session recovery withholds every request to the peer 2026-10-29 23:28:48 -04:00
Adrien Beraud fcb0632a41 docs: describe session recovery without payloads in Initial envelopes 2026-10-29 23:28:48 -04:00
Adrien Beraud 3ba61e7e4e network: recover lost sessions with a ping before resending requests 2026-10-29 23:28:48 -04:00
Adrien Beraud 4ef2c21ce0 docs: describe fragment sizes per envelope 2026-10-29 23:28:48 -04:00
Adrien Beraud d98c66b2c0 network: size value fragments by the envelope in use 2026-10-29 23:28:48 -04:00
Adrien Beraud dc09983b6b tests: require session recovery before resending payloads, and envelope-sized fragments 2026-10-29 23:28:48 -04:00
Adrien Beraud da00246fe8 docs: describe the fragment size calculation 2026-10-29 23:28:48 -04:00
Adrien Beraud e092e4d89f network: size value fragments from the minimum MTU
Fragments carried 1280 bytes of value data, plus the msgpack framing and,
for encrypted peers, the envelope overhead: packets exceeded the 1280-byte
IPv6 minimum MTU. Derive both fragment sizes from the 1232-byte UDP payload
that fits in it, less an upper bound of the fragment framing.
2026-10-29 23:28:48 -04:00
Adrien Beraud ed8131a3c6 tests: require value fragments to fit the IPv6 minimum MTU 2026-10-29 23:28:48 -04:00
Adrien Beraud f29c77cadf docs: state the scope of each transport limitation 2026-10-29 23:28:48 -04:00
Adrien Beraud d90988cb6a transport: save key files through temporary replacements 2026-10-29 23:28:48 -04:00
Adrien Beraud 3cf24c89d4 tests: require atomic transport-key state persistence 2026-10-29 23:28:48 -04:00
Adrien Beraud 5e7bcd1189 node: use compact fixed-width transport badges 2026-10-29 23:28:48 -04:00
Adrien Beraud 8ac6baee22 tests: require fixed-width node transport badges 2026-10-29 23:28:48 -04:00
Adrien Beraud f9bb4bcb40 node: show transport authentication state in logs 2026-10-29 23:28:48 -04:00
Adrien Beraud 35f486e035 tests: cover node transport state formatting 2026-10-29 23:28:48 -04:00
Adrien Beraud 0d5e4c761a network: enforce transport trust and address validation boundaries 2026-10-29 23:28:48 -04:00
Adrien Beraud efc372dc3f tests: cover transport trust and address validation boundaries 2026-10-29 23:28:48 -04:00
Adrien Beraud ddfbca3106 docs: describe fragment binding to the envelope state 2026-10-29 23:28:48 -04:00
Adrien Beraud 353c3d4e11 network: bind fragmented message parts to their envelope state
Value data fragments carry no node ID and were merged into a partial
message by source address and transaction ID alone, first come first
served. Transaction IDs increment from a random start and show in any
plaintext packet of a pair, such as the first-contact ping. An attacker
spoofing the sender's address could thus pre-seed forged plaintext
fragments, or a plaintext header, for an encrypted reply: the real parts
were then dropped as overlapping, forging unsigned values or losing the
message.

Parts of a message must now all be plaintext, or all come in envelopes
from the same sender key as its first part. An encrypted part replaces
plaintext state, which anyone can forge from a spoofed address; plaintext
or foreign-key parts never join an encrypted message.
2026-10-29 23:28:48 -04:00
Adrien Beraud 51324683e8 tests: cover forged parts in encrypted fragmented messages
Value data fragments carry no node ID. Parts of a message received in
envelopes must all come under the sender key of the envelopes, so that
plaintext or foreign-key parts spoofed from the sender's address, which
would otherwise be merged first, are ignored.
2026-10-29 23:28:48 -04:00
Adrien Beraud 4633483e06 docs: describe address-validated session caching 2026-10-29 23:28:48 -04:00
Adrien Beraud 6aee7ceb5c network: cache sessions only for address-validated peers
A session was cached for an address whenever we answered a peer there,
including replies to Initial and Hello envelopes, whose source address is
not verified. A spoofed Initial or Hello therefore replaced the session of
the real owner of the address, whose Data envelopes were then dropped until
a retry, and spoofed Initials from many addresses filled the cache and
evicted legitimate sessions, which were picked by address order.

Only cache a session for a peer whose ephemeral key arrived in a Session
or Data envelope, i.e. opened with our key for its address. Replies to
Initial and Hello envelopes derive their keys without caching them, so a
node that sent an Initial only confirms the session, and switches to Data
envelopes, once the peer answered a Session envelope. Evict the least
recently used session when the cache is full.
2026-10-29 23:28:48 -04:00
Adrien Beraud 32709230c6 tests: cover session cache hijacking by unvalidated senders
Replies to Initial and Hello envelopes must not cache a session at the
source address, which can be spoofed, and the cache must evict the least
recently used session rather than the lowest address. A node that started
with an Initial envelope only switches to Data envelopes once the peer
answered a Session envelope, which is when the peer caches the session.
2026-10-29 23:28:48 -04:00
Adrien Beraud 7b526410dd docs: describe Data envelopes and session confirmation 2026-10-29 23:28:48 -04:00
Adrien Beraud fbff1eced4 network: forget the peer ephemeral key on plaintext key advertisement
A peer only advertises its key in plaintext when it doesn't know ours, e.g. after a restart: it lost our session, so answer with an Initial envelope.
2026-10-29 23:28:48 -04:00
Adrien Beraud d23cb42b27 tests: cover a peer restarting with the same key
A node restarting with the same key and contacting a peer by address gets answers encrypted with the ephemeral key of its previous run.
2026-10-29 23:28:48 -04:00
Adrien Beraud e78e54b8c5 transport: send keyless Data envelopes once the session is confirmed
Sessions are keyed by peer address, so the receiver finds the keys from the source address: Data envelopes drop both keys from the header (30 bytes of overhead instead of 94) and need no key derivation to reject. A session is confirmed when the peer answers our envelope request with the session keys, or sends Data itself. Credentials only travel in key-carrying envelopes, which replaces Peer::acked. A received Initial envelope unconfirms the session, and full session caches evict instead of refusing, so a peer that derived keys keeps them.
2026-10-29 23:28:48 -04:00
Adrien Beraud 40560eec4e tests: cover keyless Data envelopes and session confirmation
Steady-state traffic uses Data envelopes, without sender keys nor credential, once the peer answered a request. Data envelopes only open from the session address, also authorize writes, and survive the receiver's epoch rotation.
2026-10-29 23:28:48 -04:00
Adrien Beraud 853bb1eeed docs: describe address-bound ephemeral keys and write authorization 2026-10-29 23:28:48 -04:00
Adrien Beraud 22d87a0f0e transport: replace write tokens with address-bound sessions
Ephemeral keys derive from a per-epoch secret and the peer address, so only that address learns them. A Session envelope then proves return routability: encrypted put, refresh and listen are accepted without token, and messages to encrypted peers no longer carry one (40 bytes saved). Initial envelopes cannot write. Tokens for plaintext peers move from Dht to NetworkEngine and derive from the same epoch secret. Session caches are keyed by address, and cached keys of both epochs are tried before any derivation.
2026-10-29 23:28:48 -04:00
Adrien Beraud dfb66c5a23 tests: cover session-based write authorization and address-bound keys
Encrypted writes must come in a Session envelope, whose ephemeral key is bound to the sender address. Plaintext writes still need a token, now issued by the network engine.
2026-10-29 23:28:48 -04:00
Adrien Beraud 56fcc5b918 docs: describe forward-secret transport keys
Ephemeral keys, Initial and Session key schedules, the unauthenticated
hello and the retry rule, with their security properties.
2026-10-29 23:28:48 -04:00
Adrien Beraud 26b30d4162 transport: add forward secrecy with rotated ephemeral keys
Each node rotates an ephemeral X25519 key every 30 minutes and keeps the
previous one for another period. Envelopes carry the sender static and
ephemeral keys. Session envelopes use keys derived from all four DH
combinations of static and ephemeral keys, erased with the epoch.
Initial envelopes, sent before the peer's ephemeral key is known, mix
the sender ephemeral and static keys with the receiver static key.

A hello is unauthenticated: it is only answered, without adding or
moving its claimed node. A peer is acknowledged only by a reply to a
request sent in an envelope, and a request retry restarts with an
Initial envelope and our credential.
2026-10-29 23:28:48 -04:00
Adrien Beraud 791a667fe2 tests: cover ephemeral key rotation, peer restart and hello
The previous ephemeral key is accepted for one more period, then erased.
A request retry restarts with an Initial envelope and our credential.
A hello is only answered and doesn't change what is known of its sender.
2026-10-29 23:28:48 -04:00
Adrien Beraud b693e3028b tests: cover forward-secret transport keys and envelope header
Session keys are directional and mix both static and ephemeral keys,
Initial keys are used before the peer's ephemeral key is known.
2026-10-29 23:28:48 -04:00
Adrien Beraud 3e975d530a docs: describe the transport encryption design 2026-10-29 23:28:48 -04:00
Adrien Beraud a32acbfa08 dht: persist the generated transport key in the node state
With persist_path, a transport key generated by the node is saved in the
state (owner-only file permissions) and restored on start, keeping the
node ID across restarts. Configured keys are never written to the state.
2026-10-29 23:28:48 -04:00
Adrien Beraud 43147b8791 tests: check generated transport key persistence 2026-10-29 23:28:48 -04:00
Adrien Beraud c1762af7e9 tools: add transport encryption and private network options
--no-encryption, --transport-key, --network-authority and
--network-credential configure the node; --gen-network-authority and
--issue-credential manage a private network.
2026-10-29 23:28:48 -04:00
Adrien Beraud 68b5996ba9 tests: cover encrypted transport and private networks 2026-10-29 23:28:48 -04:00
Adrien Beraud 7bc287fe2f network_engine: encrypt the DHT protocol
Nodes using transport encryption derive their node ID from their X25519
transport key, advertise it in plaintext messages ("k") and in node
lists ("k4"/"k6"), and encrypt all traffic with nodes whose key is
known. Keys are bound to node IDs, so they can't be forged, and
plaintext messages never move a node known to support encryption.
Legacy nodes keep talking in plaintext.

Private networks (TransportConfig::authorities) only accept nodes with
a credential issued by one of the network authorities, never send or
accept plaintext, and introduce themselves to addresses with a Hello.
2026-10-29 23:28:48 -04:00
Adrien Beraud 523dda8b3d tests: add transport primitives tests 2026-10-29 23:28:48 -04:00
Adrien Beraud 1c32dd0efb transport: add protocol encryption and credential primitives
X25519 transport keys, node ID derivation from the public key,
HKDF-SHA256 key agreement, ChaCha20-Poly1305 envelopes that legacy
msgpack parsers reject, and Ed25519 network authority credentials.
2026-10-29 23:28:48 -04:00
Adrien Beraud 1c914d8977 BUILD.md: cleanup 2026-10-29 23:28:29 -04:00
Adrien Beraud 3c87991e92 docs: make Rust README precise and factual 2026-10-29 22:46:57 -04:00