lib/reticulum/src/interface/root.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 //! The code every frame on one network interface carries to show it belongs
2 //! there, and the two calls that add it on the way out and check it on the way
3 //! in.
4 //!
5 //! An operator running a closed network over a shared medium wants its nodes to
6 //! take each other's frames and nothing else. The check runs on every frame in
7 //! both directions, so it has to be cheap and it has to work in the buffer the
8 //! caller already holds.
9 //!
10 //! A shared secret sent in the clear on every frame is readable by anyone
11 //! listening, so what goes on the wire has to prove knowledge of the secret
12 //! without carrying it. A frame that still looks like a Reticulum packet to an
13 //! outsider announces that the network is there. A check that stops at the
14 //! first byte that disagrees tells an attacker how much of a guess was right.
15 //!
16 //! The subtree follows Reticulum 1.5.0, the reference implementation, pinned to
17 //! one upstream commit by the package README and the generated conformance
18 //! corpus. What it takes is the key derivation of Reticulum@1.5.0
19 //! RNS/Reticulum.py:989-1002, the masking of Reticulum@1.5.0
20 //! RNS/Transport.py:1244-1276, and the checking of Reticulum@1.5.0
21 //! RNS/Transport.py:1648-1694. The package generates masked frames and verdicts
22 //! from that release and replays them in tests, so each of those claims is
23 //! checkable from this tree.
24 //!
25 //! The code a frame carries to show it belongs on one network interface (the
26 //! *access code*) is the tail of an Ed25519 signature over the packet, from one
27 //! to 64 bytes of it, taken under a key derived from the network's name and
28 //! key, so the secret stays off the wire. Every other byte of the frame is
29 //! combined with derived bytes (the *mask*) seeded by that code, which leaves
30 //! the frame looking like unstructured bytes to anyone without the key.
31 //! Checking recomputes the signature over the recovered packet and compares it
32 //! against the carried code over a fixed 64 bytes, so the comparison takes the
33 //! same time whatever the bytes are. Both directions refuse a call whose input
34 //! and output buffers overlap.
35 //!
36 //! - *interface key*: the 64 bytes derived from a network name and a network
37 //! key, which both sign the access code and key the mask.
38
39 pub const ifac = @import("ifac.zig");