lib/reticulum/src/identity/root.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 //! The key material behind one Reticulum address and everything that material
2 //! does: name itself, sign, check a signature, seal a payload for a peer, open
3 //! what arrives, and roll a short-lived key forward. An address on this network
4 //! is a hash over a dotted name and the owner's public key, so the keys here
5 //! make an address reachable by its owner alone.
6 //!
7 //! Whoever holds these bytes has to be the only party that can read what is
8 //! addressed to the name and the only one that can sign for it. The code runs
9 //! where memory is fixed before the program starts, so key values are plain
10 //! arrays and every store takes its size from the caller. A node also has to
11 //! remember what it learned about other parties from their announcements, under
12 //! the same fixed memory.
13 //!
14 //! Key bytes that travel by value leave copies the owner has no way to reach,
15 //! so erasing one copy leaves the rest. One key pair that never changes leaves
16 //! every message ever addressed to it readable once those bytes leak. The
17 //! sender picks which of a party's keys it encrypts to, so the receiver has to
18 //! work out which one was used before it can read anything.
19 //!
20 //! The subtree follows Reticulum 1.5.0, the reference implementation, pinned to
21 //! one upstream commit by the package README and the generated conformance
22 //! corpus. What it takes is the key layout of Reticulum@1.5.0
23 //! RNS/Identity.py:59-62, the encryption transcript of Reticulum@1.5.0
24 //! RNS/Identity.py:804-836, the decryption order of Reticulum@1.5.0
25 //! RNS/Identity.py:849-907, and the rotation rule of Reticulum@1.5.0
26 //! RNS/Destination.py:206-243. The package generates identity vectors from that
27 //! release and replays them in tests, so each of those claims is checkable from
28 //! this tree.
29 //!
30 //! A party's key material, private or public (*identity*), is one 64-byte value
31 //! the caller owns, and a caller that needs the bytes gone keeps a single
32 //! instance and erases it in place. A third form borrows 64 public bytes the
33 //! caller already holds, so checking a received announcement needs no copy of
34 //! the key out of the payload. The short-lived keys a party has published
35 //! (*rotating keys*) live newest first in one block of caller storage, which is
36 //! zeroed when it is taken and again when it is handed back. Decryption walks
37 //! the rotating keys a party keeps after it stops publishing them (*retained
38 //! keys*) in the order the caller gave, falls back to the identity key, and
39 //! reports which retained key opened the message. Every shared secret and
40 //! derived key is erased before the call that made it returns. The subtree
41 //! names its pieces: the key pairs, encryption and decryption, rotating keys
42 //! and the ring that holds them, and what the node remembers about other
43 //! parties.
44
45 const key = @import("key.zig");
46 const ratchet_module = @import("ratchet.zig");
47
48 pub const Private = key.Private;
49 pub const Public = key.Public;
50 pub const BorrowedPublic = key.BorrowedPublic;
51 pub const key_bytes = key.key_bytes;
52 pub const KeyBytes = key.KeyBytes;
53 pub const Rotating = @import("rotating.zig").Rotating;
54 pub const cipher = @import("cipher.zig");
55 pub const ratchet = ratchet_module;
56 pub const Ratchet = ratchet_module.Ratchet;
57 pub const Ring = ratchet_module.Ring;
58 pub const Seconds = ratchet_module.Seconds;
59 pub const known = @import("known.zig");