Session 51: Create fips-intro.md protocol introduction

New comprehensive protocol introduction replacing fips-design.md:
- What is FIPS / Why FIPS: goals and design philosophy
- How It Works: transport, spanning tree, bloom filters, routing overview
- Prior Work: Yggdrasil/Ironwood, Noise Protocol, WireGuard references
- Identity System: npub/nsec, node_id derivation, fd00::/8 addressing
- Two-Layer Encryption: link layer (Noise IK), session layer (Noise KK)
- Spanning Tree Protocol: root election, parent selection, gossip limits
- Bloom Filter Routing: filter explanation, propagation, discovery
- Transport Abstraction: transport/link distinction, bridging, types
- Security: threat model, Sybil resistance, accurate metadata exposure

Updated cross-references in README.md and other design docs.
Deleted obsolete fips-design.md.
This commit is contained in:
Johnathan Corgan
2026-02-01 20:51:01 +00:00
parent 7c2e11c5de
commit e582f50de7
7 changed files with 565 additions and 815 deletions
+14 -20
View File
@@ -7,11 +7,11 @@ Protocol design specifications and analysis for the Federated Interoperable Peer
Start with the high-level architecture, then work through session flow, routing
concepts, and finally the wire-level protocol details.
### 1. Architecture and Overview
### 1. Introduction and Overview
| Document | Description |
|------------------------------------------|-------------------------------------------------------------|
| [fips-design.md](fips-design.md) | Core protocol: goals, identity, addressing, spanning tree |
| [fips-intro.md](fips-intro.md) | Protocol introduction: goals, concepts, architecture |
### 2. Protocol Flow (How Traffic Works)
@@ -45,22 +45,16 @@ concepts, and finally the wire-level protocol details.
## Document Cross-References
```text
fips-design.md
fips-session-protocol.md
│ │
┌─────────┘ └─────────┐
fips-routing.md fips-wire-protocol.md
│ │
spanning-tree-dynamics.md │
│ │
└───────────┬───────────────────┘
fips-gossip-protocol.md
fips-transports.md
fips-intro.md
┌────────────┴────────────┐
▼ ▼
fips-session-protocol.md fips-architecture.md
│ │
┌─────────┴─────────┐
▼ ▼ fips-transports.md
fips-routing.md fips-wire-protocol.md
▼ ▼
spanning-tree-dynamics.md ←→ fips-gossip-protocol.md
```
+1 -1
View File
@@ -1040,7 +1040,7 @@ establishment).
## References
- [fips-design.md](fips-design.md) — Overall FIPS protocol design
- [fips-intro.md](fips-intro.md) — Overall FIPS protocol design
- [fips-session-protocol.md](fips-session-protocol.md) — Traffic flow, session terminology, crypto sessions
- [fips-transports.md](fips-transports.md) — Transport protocol characteristics
- [fips-routing.md](fips-routing.md) — Routing, Bloom filters, discovery
-790
View File
@@ -1,790 +0,0 @@
# FIPS: Federated Interoperable Peering System
A distributed, decentralized network routing protocol for mesh nodes connecting
over arbitrary transports. Inspired by [Yggdrasil v0.5](https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html)
but adapted for the Nostr ecosystem with multi-transport flexibility.
## Design Goals
1. **Nostr-native identity** - Use Nostr keypairs as node identities
2. **Transport agnostic** - Support IP, wireless, serial, onion, and other link types
3. **Self-organizing** - Automatic topology discovery and route optimization
4. **Privacy preserving** - Minimize metadata leakage across untrusted links
5. **Resilient** - Self-healing with graceful degradation
6. **Reuse Nostr primitives** - Leverage cryptographic primitives already in use in
the Nostr ecosystem (secp256k1, Schnorr signatures, SHA-256) to simplify
implementation and reduce dependency surface
## Architecture Overview
```
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ (Nostr clients, services, bridges) │
├─────────────────────────────────────────────────────────────┤
│ FIPS Router │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Identity │ │ Spanning │ │ Bloom Filter │ │
│ │ (npub) │ │ Tree │ │ Routing Table │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Transport Abstraction │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ TCP │ │ QUIC │ │ Radio │ │ Serial │ │ Onion │ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────┘
```
---
## 1. Identity System
### Node Identity
FIPS uses Nostr keypairs (secp256k1) directly as node identities. There is no need
for the clustering properties that Yggdrasil's Ed25519 bit-inversion scheme provides;
the spanning tree handles all routing structure.
Node addresses use an IPv6-compatible format to facilitate reuse of applications
designed for IP transports (e.g., binding to a FIPS address via a TUN interface).
This does not imply that peering over existing IPv4 or IPv6 networks is required—FIPS
supports arbitrary transports including radio, serial, and other non-IP links.
Nonetheless, it is anticipated that the majority of FIPS peers will connect via
the public Internet.
### Node ID and Address Derivation
```text
nostr_npub (secp256k1 x-only, 32 bytes)
▼ SHA-256
node_id (32 bytes)
▼ Truncate with prefix
fips_address (128 bits)
```
The full 32-byte `node_id` is used in protocol messages and bloom filters.
The truncated 128-bit address is used for IPv6 compatibility.
**Why hash the npub?** Secp256k1 public keys can be "ground" to achieve specific
prefixes more efficiently than brute force via modular addition (adding a known
value to the private key shifts the public key predictably). Hashing eliminates
this shortcut—targeting a specific node_id prefix requires full brute force
against SHA-256, making node ID grinding as expensive as the hash strength allows.
**Separation of concerns**: The nsec/npub keypair is used exclusively for
cryptographic operations (signing protocol messages, identity verification,
end-to-end encryption). The node_id derived from the npub is used only for
routing network traffic. This separation keeps cryptographic material out of
routing tables and packet headers.
### Address Format
FIPS addresses use the IPv6 Unique Local Address (ULA) prefix `fd00::/8`. This
provides 120 bits for the node_id hash while avoiding conflicts with global
unicast addresses that may be in use on underlying IPv6 transports.
```text
FIPS Address (128 bits):
┌────────┬────────────────────────────────────────────────────┐
│ 0xfd │ node_id[0:15] │
│ 8 bits │ 120 bits │
└────────┴────────────────────────────────────────────────────┘
```
FIPS addresses are overlay identifiers, not routable IPv6 addresses. They never
appear in IPv6 headers on the underlying transport; the `fd` prefix simply ensures
no collision with addresses that may be legitimately in use on that transport.
### Identity Verification
FIPS uses two complementary signing mechanisms:
**General signing** is used for protocol messages (TreeAnnounce, LookupResponse,
etc.) where the signer is asserting authorship of data:
```text
signature = schnorr_sign(nsec, SHA256(message))
```
**Challenge-response authentication** is used during connection establishment
to prove a node controls the private key corresponding to its claimed npub.
### Peer Authentication Protocol (Noise IK)
When two nodes establish a connection, they perform mutual authentication using
the Noise Protocol Framework with the IK pattern. This provides:
- Mutual authentication (both parties prove identity)
- Forward secrecy (ephemeral keys protect past sessions)
- Encrypted link (all subsequent messages are encrypted)
> **Terminology note**: *Peer authentication* (this section) is hop-by-hop—it
> verifies that a direct peer is who they claim to be and establishes an
> encrypted link. This is distinct from *session-layer encryption* which
> provides end-to-end authenticated encryption between FIPS addresses. Both
> layers operate independently: peer auth secures each link; session encryption
> secures the full path.
#### Protocol: Noise_IK_secp256k1_ChaChaPoly_SHA256
The IK pattern is chosen because:
- **Outbound connections**: Initiator knows responder's static key from config
- **Inbound connections**: Responder learns initiator's identity from message 1
```text
Pre-message (known before handshake):
<- s (responder's static key known to initiator)
Handshake:
-> e, es, s, ss (msg1: initiator sends ephemeral + encrypted static)
<- e, ee, se (msg2: responder sends ephemeral)
```
```text
Initiator (A) Responder (B)
│ │
│ knows B's npub from config │
│ │
│───── msg1 (82 bytes) ──────────────────────►│
│ e: ephemeral pubkey (33) │
│ s: encrypted static (33+16) │
│ │ learns A's identity
│◄───── msg2 (33 bytes) ──────────────────────│
│ e: ephemeral pubkey (33) │
│ │
▼ ▼
Noise session established Noise session established
(symmetric keys derived) (symmetric keys derived)
```
#### Cryptographic Primitives
| Component | Choice | Notes |
|-----------|---------------------|---------------------------|
| Curve | secp256k1 | Nostr-native |
| DH | ECDH on secp256k1 | Standard EC Diffie-Hellman|
| AEAD | ChaCha20-Poly1305 | Same as NIP-44 |
| Hash | SHA-256 | Nostr-native |
| KDF | HKDF-SHA256 | Standard Noise KDF |
#### Crossing Connection Handling
When both nodes simultaneously initiate connections, a deterministic tie-breaker
resolves which connection survives:
```text
Rule: Smaller node_id's OUTBOUND connection wins
If our_node_id < their_node_id:
- Our outbound wins, close our inbound
If our_node_id > their_node_id:
- Our inbound wins, close our outbound
```
Both nodes independently reach the same conclusion without coordination.
#### Post-Authentication State
After the Noise handshake completes:
- **NoiseSession** holds symmetric keys for encrypt/decrypt
- Link is fully encrypted (all subsequent messages use AEAD)
- Peer's verified identity is extracted from the handshake
- Node transitions from `PeerConnection` to `ActivePeer` state
#### Link vs Session Encryption
FIPS uses two independent encryption layers:
| Layer | Scope | Keys | Purpose |
|-------------|-------------|--------------------------|--------------------------------------|
| **Link** | Hop-by-hop | Per-peer Noise session | Encrypt all traffic on this link |
| **Session** | End-to-end | Per-destination session | Encrypt payload across multiple hops |
A packet from A→D through B traverses:
1. A encrypts payload with A↔D session key
2. A encrypts that with A↔B link key, sends to B
3. B decrypts link layer, routes, re-encrypts with B↔C or B↔D link key
4. D decrypts link layer, then decrypts session layer to get payload
Intermediate nodes can route but cannot read session-layer payloads.
---
## 2. Spanning Tree Protocol
### Background
A spanning tree is a subgraph of a mesh network that includes all nodes but
contains no cycles. It has the following properties:
- **Unique paths**: Exactly one path exists between any two nodes
- **N-1 edges**: A spanning tree with N nodes has exactly N-1 edges
- **Minimal connectivity**: Removing any edge disconnects the tree
A *minimum* spanning tree optimizes for some metric across all edges—typically
minimizing total cost, latency, or hop count. In FIPS, parent selection considers
link quality metrics, causing the tree to approximate a minimum spanning tree
with respect to those metrics.
In a distributed system, nodes construct a spanning tree by each selecting a
single parent. The result is a rooted tree where every node can reach every
other node by traversing toward their lowest common ancestor.
### Purpose
The spanning tree provides the routing backbone for FIPS. Unlike traditional
routing protocols that require global routing tables or centralized coordination,
the spanning tree creates a distributed structure that enables:
- **Destination lookup**: Finding the current location of any node by its node_id
- **Greedy forwarding**: Routing packets toward their destination without source routes
- **Multicast scope**: Limiting lookup broadcasts to relevant subtrees via bloom filters
### Design Criteria
1. **Minimal state**: Each node maintains only its parent selection and immediate
peer information, not global topology
2. **Rapid convergence**: Topology changes propagate quickly through gossip
3. **Partition tolerance**: Isolated network segments form independent trees that
merge when connectivity is restored
4. **Transport-aware**: Parent selection considers link quality, not just reachability
5. **Byzantine tolerance**: Malicious nodes cannot claim arbitrary tree positions
without valid signatures
### Relationship to Yggdrasil
The spanning tree protocol is based on concepts proven in Yggdrasil v0.5 / Ironwood.
Deviations from that design are noted where applicable.
### Tree State
The spanning tree is maintained as a distributed data structure with CRDT
(Conflict-free Replicated Data Type) semantics. This provides eventual consistency
without requiring coordination: nodes can make local decisions about parent
selection, gossip updates to peers, and the system converges to a consistent
global view.
Each node selects exactly one parent (or itself if it believes it is root) and
has zero or more peers (direct connections over any transport). Through gossip,
each node learns about other nodes' parent selections, building a local view of
the tree.
Each peer's TreeAnnounce message includes its full ancestry—the chain of parent
selections from that peer up to the root. This means a node's TreeState contains:
- **Direct peers**: Their parent selections received directly
- **Ancestors of peers**: Every node on the path from each peer to the root
This ancestry information is essential for computing tree coordinates and the
distance metric used in greedy routing.
```text
TreeState = {
(node_id, parent_id, sequence, signature, timestamp),
(node_id, parent_id, sequence, signature, timestamp),
...
}
```
**Generating announcements**: A node generates a new TreeAnnounce when:
- It selects a new parent (including initial startup)
- A periodic refresh interval expires (to maintain liveness)
- It detects its parent has become unreachable
Each announcement contains the node's current parent selection, an incremented
sequence number, a timestamp, and a Schnorr signature over these fields. The
announcement also includes the node's full ancestry—the chain of parent
declarations from itself up to the current root.
**Processing received announcements**: When a node receives a TreeAnnounce from
a peer, it:
1. Verifies the signature on the sender's parent declaration
2. Verifies signatures on each entry in the ancestry chain
3. Validates that the ancestry forms a coherent path to a valid root
4. Merges each entry into its local TreeState
**Merge rules**: When merging an entry for a given node_id:
- Higher sequence number always wins
- On sequence tie, prefer the entry with the later timestamp
- On both tie, prefer lexicographically smaller parent_id (deterministic)
- Entries not refreshed within the TTL are expired and removed
These rules ensure all nodes converge to the same TreeState view despite
receiving updates in different orders.
### Root Election
The root of the spanning tree is the node with the lexicographically smallest
node_id among all nodes a given node can reach. This election is deterministic
and requires no explicit coordination—each node independently arrives at the
same conclusion from its local TreeState.
**Startup behavior**: A newly joined node initially considers itself the root
(parent = self). As it receives TreeAnnounce messages from peers, it discovers
nodes with smaller node_ids and adopts a new parent whose ancestry leads to
the smallest known node_id.
**Partition behavior**: If the network partitions, each isolated segment elects
its own root (the smallest node_id within that segment). When partitions merge,
nodes in the segment with the larger root discover the globally smaller root
and re-parent accordingly. The tree reconverges automatically.
### Parent Selection
Each node selects a parent that provides the best path to the current root,
considering both reachability and link quality. The parent must be a direct
peer—nodes cannot select non-peers as parents.
**Stability mechanism**: To prevent flapping during minor topology changes, a
node only changes its parent if the improvement exceeds a threshold. This
hysteresis ensures the tree remains stable under transient conditions.
**Selection criteria**:
1. The candidate parent must have a path to the current root
2. Among valid candidates, prefer the one with lowest effective cost
3. Only switch if the improvement exceeds the stability threshold
### Tree Coordinates
A node's coordinate is its path to root:
```text
Coordinate = [self_id, parent_id, ..., root_id]
```
Coordinates are ordered self-to-root, so common ancestry is a suffix. This
ordering is consistent across all FIPS documents.
**Distance metric**: Tree distance between two nodes is the sum of hops to their
lowest common ancestor (LCA). With self-to-root ordering, the LCA is found by
comparing coordinate suffixes:
```
dist(A, B) = depth(A) + depth(B) - 2 * depth(LCA(A, B))
```
### Gossip Efficiency
Two strategies reduce gossip bandwidth:
**Delta encoding**: A node tracks the last sequence number sent to each peer for
each ancestor. Subsequent announcements omit entries that haven't changed since
the last transmission to that peer. This optimization is always beneficial—it
reduces bandwidth without affecting convergence.
**Partial ancestry**: On severely constrained links, a node may send only its
immediate parent declaration, relying on transitive propagation through other
gossip paths to eventually deliver the full ancestry.
The tradeoff with partial ancestry is convergence speed. With full ancestry, the
recipient immediately knows the sender's complete tree coordinate, can compute
accurate distances, and can route packets right away. With parent-only, the
recipient must wait for the remaining ancestors to propagate through other paths
before routing works correctly. On high-bandwidth links, the extra bytes for full
ancestry are cheap and provide immediate usability. On a 300 bps radio link,
accepting slower convergence may be necessary to avoid transmitting a long chain
of ancestor entries.
### Cost Metrics
Parent selection and routing decisions depend on link cost metrics. The primary
metrics are:
- **Latency**: Round-trip time for the link
- **Packet loss**: Proportion of packets that fail to arrive
- **Bandwidth**: Available throughput capacity
These metrics combine into an effective cost used for parent selection and
routing decisions. The specific formula for combining metrics, the measurement
methodology, and the weighting of each factor are areas for future specification.
---
## 3. Bloom Filter Routing
### Yggdrasil Design
- 8192-bit bloom filter (1024 bytes)
- 8 hash functions per key
- False positive rate ~1/million for 200-node subtree
- Saturates in network core (acts as default route)
### Lookup Protocol
When a node needs to reach an unknown destination:
1. Create lookup packet with destination key
2. Forward to on-tree peers whose bloom filter contains the key
3. If multiple matches, send to all (multicast)
4. Destination responds with its current coordinates
5. Sender caches coordinate for direct routing
### FIPS Adaptations
**Tunable filter size**: Different deployments may need different tradeoffs:
| Scenario | Filter Size | Hash Functions | Target Nodes |
|----------|-------------|----------------|--------------|
| Small mesh (<100) | 2048 bits | 4 | 50 |
| Medium network | 8192 bits | 8 | 500 |
| Large network | 32768 bits | 12 | 2000 |
**Filter compression**: For low-bandwidth links (radio), use:
- Compressed bloom filter representation
- Hierarchical filters (subnet then node)
- Lazy propagation with invalidation
**Key transformation**: Allow filtering on npub prefixes for subnet routing:
```
filter.add(SHA256(npub)[0:8]) // 64-bit prefix for subnet
filter.add(SHA256(npub)) // Full key for node
```
---
## 4. Greedy Routing
### Algorithm
```
route(packet, destination):
if destination == self:
deliver(packet)
return
best_peer = None
best_distance = tree_distance(self, destination)
for peer in connected_peers:
d = tree_distance(peer, destination)
if d < best_distance:
best_distance = d
best_peer = peer
if best_peer:
forward(packet, best_peer)
else:
send_path_broken(packet.source)
```
### Path-Broken Recovery
When greedy routing fails (local minimum):
1. Send path-broken notification back to source
2. Source initiates bloom filter lookup for destination
3. On response, source caches new coordinates
4. Retry with updated routing information
---
## 5. Transport Abstraction Layer
FIPS is transport-agnostic. Transports are the physical or logical interfaces
over which FIPS communicates (UDP sockets, Ethernet NICs, Tor clients, etc.).
Links are connection instances to specific peers over a transport.
> **Note**: The Transport trait definition and detailed transport specifications
> are in [fips-architecture.md](fips-architecture.md). This section provides a
> conceptual overview. See [fips-transports.md](fips-transports.md) for transport
> characteristics and requirements.
### Transport Interface Concept
Each transport driver provides:
- **Identity**: Transport type identifier and configuration
- **Lifecycle**: Start/stop the transport interface
- **I/O**: Send/receive datagrams to/from transport-layer addresses
- **Discovery**: Find potential peers (transport-specific mechanism)
- **MTU**: Maximum packet size for this transport
Transports handle framing, fragmentation, and any transport-layer encryption
internally. The FIPS routing layer sees only FIPS packets.
### Transport Types
#### TCP/TLS Transport
Standard Yggdrasil-style IP peering with TLS encryption.
#### QUIC Transport
UDP-based with built-in encryption and multiplexing.
#### Radio Transport (LoRa, HF, VHF/UHF)
- Packet-based with size limits
- May support broadcast
- Often asymmetric (different TX/RX capabilities)
- Requires careful bandwidth management
#### Serial Transport (RS-232, USB, etc.)
- Point-to-point
- Framing protocol needed (SLIP, HDLC, etc.)
- Good for isolated node pairs
#### Onion Transport (Tor, I2P)
- High latency
- Strong anonymity properties
- Special handling for circuit setup
#### Bluetooth/BLE Transport
- Short range
- Discovery via scanning
- Pairing considerations
### Multi-Transport Routing
A single node may have multiple transports of different types:
```
┌─────────────────────────────────────────┐
│ FIPS Node │
│ ┌─────────────────────────────────┐ │
│ │ Router Core │ │
│ └──────────┬──────────┬───────────┘ │
│ │ │ │
│ ┌──────┴────┐ ┌───┴─────┐ │
│ │ TCP │ │ LoRa │ │
│ │ Transport │ │Transport│ │
│ └────┬──────┘ └────┬────┘ │
└───────────┼─────────────┼──────────────┘
│ │
┌────┴────┐ ┌─────┴────┐
│Internet │ │ Radio │
│ Peers │ │ Peers │
└─────────┘ └──────────┘
```
**Transport selection for forwarding**:
- Prefer transport with best path to destination
- Consider transport characteristics (don't send bulk over LoRa)
- Support explicit transport preferences in routing hints
---
## 6. Protocol Messages
FIPS uses a discriminator-based wire format with session indices for efficient
dispatch. See [fips-wire-protocol.md](fips-wire-protocol.md) for complete
wire format specification, security properties, and dispatch logic.
### Wire Format
All FIPS link-layer packets begin with a 1-byte discriminator:
```text
┌─────────────┬────────────────────────────────────────────────┐
│ Discriminator│ Type-Specific Payload │
│ 1 byte │ Variable │
└─────────────┴────────────────────────────────────────────────┘
```
| Byte | Type | Payload Format |
|------|-----------------|--------------------------------------------------|
| 0x00 | Encrypted frame | `[receiver_idx:4][counter:8][ciphertext+tag]` |
| 0x01 | Noise IK msg1 | `[sender_idx:4][noise_msg1:82]` |
| 0x02 | Noise IK msg2 | `[sender_idx:4][receiver_idx:4][noise_msg2:33]` |
**Session indices** enable O(1) dispatch without relying on source address,
supporting transport-layer roaming. Each party allocates a random 32-bit index
during handshake; packets include the receiver's index for fast session lookup.
### Handshake Messages
Exchanged during Noise IK handshake before link encryption is established.
| Type | Name | Size | Description |
|------|-------------|----------|-------------------------------------------------|
| 0x01 | NoiseIKMsg1 | 87 bytes | Initiator: index + ephemeral + encrypted static |
| 0x02 | NoiseIKMsg2 | 42 bytes | Responder: indices + ephemeral pubkey |
### Encrypted Frames
Post-handshake packets use the 0x00 discriminator with AEAD encryption:
- **receiver_idx**: Identifies session for O(1) lookup (no trial decryption)
- **counter**: 64-bit monotonic nonce, also used for replay detection
- **ciphertext**: ChaCha20-Poly1305 encrypted payload with 16-byte tag
The plaintext begins with a message type byte (see Link Layer Messages below).
### Link Layer Messages (0x10-0x4F)
Exchanged between directly connected peers over Noise-encrypted links.
All payloads are encrypted with session keys from the Noise IK handshake.
| Type | Name | Description |
|------|----------------|--------------------------------------------|
| 0x10 | TreeAnnounce | Spanning tree state announcement |
| 0x20 | FilterAnnounce | Bloom filter reachability update |
| 0x30 | LookupRequest | Request to discover node coordinates |
| 0x31 | LookupResponse | Response with target's coordinates |
| 0x40 | SessionDatagram| Encapsulated session-layer payload |
### Session Layer Messages (End-to-End)
Carried inside `SessionDatagram`, encrypted with end-to-end session keys.
Intermediate nodes route based on destination but cannot read the payload.
| Type | Name | Description |
|------|----------------|--------------------------------------------|
| 0x00 | SessionSetup | Session establishment with coordinates |
| 0x01 | SessionAck | Session acknowledgement |
| 0x10 | DataPacket | Encrypted IPv6 datagram |
| 0x20 | CoordsRequired | Router cache miss notification |
| 0x21 | PathBroken | Route failure notification |
See [fips-routing.md](fips-routing.md) Part 4 for routing session details.
### TreeAnnounce
```
TreeAnnounce {
sender: [u8; 32], // npub
sequence: u64,
parent: [u8; 32], // parent npub (self if root)
ancestry_count: u8,
ancestry: [(pubkey, seq, sig), ...],
signature: [u8; 64], // Schnorr signature
}
```
### BloomUpdate
```
BloomUpdate {
sender: [u8; 32],
link_id: u32, // Which peer link this filter is for
filter_size: u16, // In bits
filter: [u8; ...], // Bloom filter bytes
sequence: u64,
}
```
### Lookup / LookupResponse
```
Lookup {
source: [u8; 32],
destination: [u8; 32],
ttl: u8,
nonce: [u8; 16],
}
LookupResponse {
destination: [u8; 32],
nonce: [u8; 16], // Echo from request
coordinates: Vec<[u8; 32]>, // Path to root [self, parent, ..., root]
signature: [u8; 64],
}
```
---
## 7. Security Considerations
### Threat Model
- **Passive adversary**: Can observe traffic on controlled links
- **Active adversary**: Can inject, modify, or drop packets
- **Sybil attacks**: Can create many identities
### Mitigations
**Signature verification**: All protocol messages signed by sender's nsec.
**Replay protection**: Sequence numbers and timestamps on tree announcements.
**Sybil resistance**:
- Tree coordinate verification (can't claim arbitrary position)
- Optional proof-of-work for identity registration
- Web-of-trust integration with Nostr follows graph
**Traffic analysis**:
- Padding options for fixed-size packets
- Chaff traffic on idle links
- Onion routing mode for sensitive traffic
### Encryption
**Link encryption**: Each link type provides its own encryption:
- TCP: TLS 1.3
- QUIC: Built-in TLS
- Radio: Pre-shared key or public-key encryption
**End-to-end encryption**: FIPS provides a crypto session layer using the Noise
Protocol Framework with secp256k1. The Noise KK pattern provides mutual
authentication and forward secrecy in a single round-trip, since both parties
know each other's npub before initiating. Session keys are used with
ChaCha20-Poly1305 AEAD for all data packets; no per-packet signatures are
required (AEAD tag provides integrity and authenticity). See
[fips-session-protocol.md](fips-session-protocol.md) §6 for crypto session details.
> **Note**: Applications may use additional encryption (NIP-44) for
> application-layer privacy, but FIPS-layer encryption protects against
> intermediate router observation.
---
## 8. Open Questions
1. **Root stability**: How to prevent root flapping in large networks?
Yggdrasil uses cost thresholds, but this may need tuning for heterogeneous links.
2. **Multi-path routing**: Should FIPS support simultaneous paths through different
link types? Useful for redundancy and bandwidth aggregation.
3. **Bloom filter propagation on slow links**: How to handle 1KB filter updates
over 300 bps radio links? Differential updates? Hierarchical filters?
4. **NAT traversal**: Yggdrasil relies on TCP for NAT punch-through. How do other
transports handle this? (Not applicable to radio/serial)
5. **Incentives**: Should there be any incentive mechanism for relaying traffic?
Or rely on reciprocal altruism?
6. **Nostr relay integration**: Can FIPS nodes announce themselves via Nostr relays?
Use kind 10002-style relay lists for FIPS peer discovery?
7. **IPv6 integration**: Should FIPS addresses be routable IPv6, or use a private
range with translation at gateways?
---
## References
### FIPS Design Documents
- [fips-session-protocol.md](fips-session-protocol.md) — Traffic flow, session terminology, crypto sessions
- [fips-routing.md](fips-routing.md) — Bloom filters, discovery, routing sessions
- [fips-architecture.md](fips-architecture.md) — Software architecture, configuration
- [fips-transports.md](fips-transports.md) — Transport protocol characteristics
- [spanning-tree-dynamics.md](spanning-tree-dynamics.md) — Tree protocol dynamics
### External References
- [Yggdrasil Network](https://yggdrasil-network.github.io/)
- [Yggdrasil v0.5 Release Notes](https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html)
- [Ironwood Routing Library](https://github.com/Arceliar/ironwood)
- [Nostr Protocol](https://github.com/nostr-protocol/nips)
- [NIP-44 Encryption](https://github.com/nostr-protocol/nips/blob/master/44.md)
+546
View File
@@ -0,0 +1,546 @@
# FIPS: Federated Interoperable Peering System
## What is FIPS?
FIPS is a self-organizing mesh network that can operate over any transport
medium—radio, serial links, Tor, local networks, or the existing internet as
an overlay. The long-term goal is infrastructure that can function alongside
or ultimately replace dependence on the Internet.
Nodes in the mesh route traffic for each other using Nostr identities (npubs)
as network addresses. Applications can access the mesh through a native FIPS
datagram service, or through an IPv6 adaptation layer that presents each node
as an IPv6 endpoint for compatibility with existing IP-based applications.
## Why FIPS?
**Infrastructure independence**: The internet depends on centralized
infrastructure—ISPs, backbone providers, DNS, certificate authorities. FIPS
works over any transport that can carry packets: a LoRa radio link between
mountain towns, a serial cable between air-gapped systems, onion-routed
connections through Tor, or the existing internet as an overlay. When the
internet is unavailable, unreliable, or untrusted, the mesh still works.
**End-to-end security**: FIPS provides secure, authenticated, and encrypted
communication between any two nodes in the mesh, independent of the mix of
transports used along the routed path between them.
**Privacy by design**: Traffic flows through encrypted tunnels at every hop.
Intermediate nodes route packets but cannot read their contents. Metadata
exposure is limited to direct peers only.
**Zero configuration**: Nodes discover each other and build routing
automatically. Connect to one peer and you can reach the entire mesh. The
network self-heals around failures and adapts to changing topology.
**Self-sovereign identity**: FIPS nodes generate their own addresses, node IDs,
and security credentials without coordination with any central authority. The
identity system uses Nostr keypairs (secp256k1), so existing npub/nsec pairs
work directly.
## How It Works (Overview)
Each FIPS node selects which transports to use (Ethernet, radio links, internet
overlay, etc.) and which peer nodes to connect to. From these local peering
decisions, the distributed spanning tree and bloom filter propagation algorithms
self-organize reachability and path information throughout the mesh.
Nodes form a spanning tree rooted at a deterministically-elected node. Each
node knows its path to the root, enabling shortest-path routing to be
calculated between any two nodes (not necessarily through the root). Bloom filters propagate reachability information so nodes can find
each other. Traffic flows via greedy routing toward destinations, encrypted
end-to-end.
Nodes with multiple transports automatically bridge between networks—the same
routing logic works regardless of the underlying transport mix.
## Design Goals
1. **Nostr-native identity** - Use Nostr keypairs as node identities
2. **Transport agnostic** - Support IP, wireless, serial, onion, and other link types
3. **Self-organizing** - Automatic topology discovery and route optimization
4. **Privacy preserving** - Minimize metadata leakage across untrusted links
5. **Resilient** - Self-healing with graceful degradation
6. **Reuse Nostr primitives** - Leverage secp256k1, Schnorr signatures, and SHA-256
## Architecture Overview
```
┌─────────────────────────────────────────────────────────────┐
│ Application Layer │
│ (native FIPS API, or IPv6 via TUN adapter) │
├─────────────────────────────────────────────────────────────┤
│ FIPS Router │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Identity │ │ Spanning │ │ Bloom Filter │ │
│ │ (npub) │ │ Tree │ │ Routing Table │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Transport Abstraction │
│ ┌────────┐ ┌──────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ UDP │ │ Ethernet │ │ WiFi │ │ Radio │ │ Onion │ │
│ └────────┘ └──────────┘ └────────┘ └────────┘ └────────┘ │
└─────────────────────────────────────────────────────────────┘
```
Applications can use the native FIPS datagram service directly, or access the
mesh through an IPv6 adaptation layer (TUN device) for compatibility with
existing IP-based applications. The router handles discovery, routing, and
encryption transparently in either case.
See [fips-transports.md](fips-transports.md) for transport options and characteristics.
## Prior Work
FIPS builds on proven designs rather than inventing new cryptography or routing
algorithms.
**Routing**: The spanning tree coordinates, bloom filter discovery, and greedy
routing algorithms are adapted from [Yggdrasil v0.5](https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html)
and its [Ironwood](https://github.com/Arceliar/ironwood) routing library. FIPS
adapts these for multi-transport operation and Nostr identity integration.
**Encryption**: Link and session encryption use the [Noise Protocol
Framework](https://noiseprotocol.org/), the same foundation used by WireGuard,
Lightning Network, and other production systems. FIPS uses the IK pattern for
link authentication and KK pattern for end-to-end sessions.
**Cryptographic primitives**: FIPS reuses Nostr's cryptographic stack—secp256k1
for keys, Schnorr signatures, SHA-256 for hashing, and ChaCha20-Poly1305 for
authenticated encryption. No novel cryptography.
**Session management**: The index-based session dispatch follows WireGuard's
approach, enabling O(1) packet routing without relying on source addresses.
---
## Identity System
FIPS uses Nostr keypairs (secp256k1) as node identities. The public key (npub)
identifies the node; the private key (nsec) signs protocol messages and
establishes encrypted sessions.
### Node ID Derivation
The npub is hashed to derive a node_id used for routing:
```
npub (secp256k1 x-only pubkey, 32 bytes)
→ SHA-256
→ node_id (32 bytes)
→ truncate with prefix
→ FIPS address (128 bits, fd::/8)
```
**Why hash the npub?** The node_id is the only identifier used at the protocol
level; the associated npub cannot be derived from it. This one-way derivation
also prevents "grinding" attacks—secp256k1 public keys can be shifted to achieve
specific prefixes via modular addition, but targeting a node_id prefix requires
full brute force against SHA-256.
**Separation of concerns**: The nsec/npub keypair handles cryptographic
operations (signing, encryption). The node_id derived from the npub handles
routing. This keeps cryptographic material out of routing tables and packet
headers.
### Address Format
When using the IPv6 protocol adapter, FIPS addresses use the IPv6 Unique Local
Address (ULA) prefix `fd00::/8`, providing 120 bits from the node_id hash.
These are overlay identifiers—they appear in the TUN interface for application
compatibility but are not routable on the underlying transport. The fd prefix
ensures no collision with addresses that may be in use on the transport network.
FIPS provides a local DNS service that maps npub bech32 names to IPv6 addresses
for this purpose.
### Identity Verification
The Noise Protocol Framework is used to mutually authenticate both peer-to-peer
link connections and end-to-end session traffic, proving each party controls
the private key for their claimed identity.
See [fips-wire-protocol.md](fips-wire-protocol.md) for the Noise IK handshake
and [fips-session-protocol.md](fips-session-protocol.md) for end-to-end
session establishment.
---
## Two-Layer Encryption
FIPS uses independent encryption at two layers:
| Layer | Scope | Pattern | Purpose |
|-------------|-------------|----------|--------------------------------------|
| **Link** | Hop-by-hop | Noise IK | Encrypt all traffic on each link |
| **Session** | End-to-end | Noise KK | Encrypt payload across multiple hops |
### Link Layer (Peer-to-Peer)
When two nodes establish a direct connection, they perform a Noise IK handshake.
This authenticates both parties and establishes symmetric keys for encrypting
all traffic on that link. Every packet between direct peers is encrypted—gossip
messages, routing queries, and forwarded traffic alike.
The IK pattern is used because outbound connections know the peer's npub from
configuration, while inbound connections learn the initiator's identity from
the first handshake message.
### Session Layer (End-to-End)
For traffic between non-adjacent nodes, FIPS establishes end-to-end encrypted
sessions using Noise KK. Both parties know each other's npub before initiating,
enabling mutual authentication in a single round-trip.
A packet from A to D through intermediate node B:
1. A encrypts payload with A↔D session key
2. A encrypts that with A↔B link key, sends to B
3. B decrypts link layer, sees destination, re-encrypts with B↔D link key
4. D decrypts link layer, then decrypts session layer to get payload
Intermediate nodes can route based on destination address but cannot read
session-layer payloads.
FIPS session setup also warms up route caches along the path between the
endpoints, so that when application traffic flows the network is already ready.
See [fips-wire-protocol.md](fips-wire-protocol.md) for link encryption and
[fips-session-protocol.md](fips-session-protocol.md) for session encryption.
---
## Spanning Tree Protocol
The spanning tree is a subset of the full mesh network that connects all nodes,
forming a tree structure rooted at a deterministically-elected node. Each node
selects a single parent, and the resulting tree serves as the routing backbone.
This enables routing without global routing tables.
### Why a Spanning Tree?
A spanning tree has useful properties:
- **Unique paths**: Exactly one path exists between any two nodes
- **Minimal state**: Nodes only track their parent and immediate peers
- **Coordinates**: A node's position in the tree enables distance calculations
The tree provides structure for routing while bloom filters provide reachability
information. Together they enable efficient packet delivery without requiring
nodes to know the full network topology.
### Tree Coordinates
A node's coordinate is its path from itself to the root. The distance between
two nodes is the sum of hops from each to their lowest common ancestor (LCA).
This distance metric enables greedy routing: forward packets to the peer that
minimizes distance to the destination.
### Root Election
The root is the node with the lexicographically smallest node_id among all
reachable nodes. This election is deterministic and requires no coordination—
each node independently examines its view of the network and reaches the same
conclusion.
The root provides a coordinate reference point but does not participate in
routing unless the paths from source and destination to the root share no
common ancestors (i.e., the root is their lowest common ancestor).
### Parent Selection
Each node selects a parent that provides the best path to root, considering:
- Reachability (the parent must have a path to root)
- Link quality (latency, packet loss, bandwidth)
- Stability (hysteresis prevents flapping on minor changes)
The parent must be a direct peer—nodes cannot select non-peers as parents.
### Tree Gossip
Nodes exchange TreeAnnounce messages containing their parent selection and
ancestry chain (path to root). When a node changes its parent, it announces the
change; peers propagate relevant updates. The tree converges through this
gossip without centralized coordination.
Changes propagate only as far as they need to—distantly connected nodes are
unaffected by local path changes and don't receive updates for them.
### Partition Handling
If the network partitions, each isolated segment elects its own root (the
smallest node_id within that segment). When partitions merge, nodes in the
segment with the larger root discover the globally smaller root and re-parent.
The tree reconverges automatically.
See [fips-routing.md](fips-routing.md) for routing concepts,
[fips-gossip-protocol.md](fips-gossip-protocol.md) for message formats, and
[spanning-tree-dynamics.md](spanning-tree-dynamics.md) for convergence behavior.
---
## Bloom Filter Routing
Tree coordinates enable routing once you know a destination's position. Bloom
filters enable finding that position in the first place.
A bloom filter is a space-efficient probabilistic data structure that can test
whether an element is a member of a set. It may produce false positives (saying
an element is present when it isn't) but never false negatives. This makes it
ideal for routing: a node can quickly check if a destination might be reachable
through a given peer, with occasional false positives handled by backtracking.
### How It Works
Each node maintains bloom filters summarizing which node_ids are reachable
through each of its peers. These filters propagate through the tree: a node
aggregates filters from its children and announces the combined filter to its
parent (and vice versa).
When a node needs to reach an unknown destination:
1. Check local bloom filters—which peers might be able to reach this node_id?
2. Send a LookupRequest to peers whose filters indicate "maybe"
3. The request propagates through the tree toward matching subtrees
4. The destination responds with a LookupResponse containing its coordinates
5. The sender caches the coordinates and routes directly via greedy forwarding
Bloom filters have false positives (a filter may indicate "maybe" when the node
isn't actually reachable through that path) but no false negatives. Extra
queries are harmless; missing a reachable node is not.
### Filter Propagation
Filters propagate in the opposite direction from tree announcements:
- Tree state propagates upward (toward root) via ancestry chains
- Bloom filters propagate downward (toward leaves) via subtree aggregation
A node's filter contains all node_ids reachable through its subtree. The root's
filter contains everyone; leaf nodes have empty outbound filters.
See [fips-routing.md](fips-routing.md) for bloom filter design and
[fips-gossip-protocol.md](fips-gossip-protocol.md) for FilterAnnounce format.
---
## Greedy Routing
Once a destination's tree coordinates are known, packets are forwarded using
greedy routing: at each hop, forward to the peer that minimizes tree distance
to the destination.
### The Algorithm
1. If I am the destination, deliver the packet locally
2. Calculate my tree distance to the destination
3. For each peer, calculate their tree distance to the destination
4. Forward to the peer with the smallest distance (must be less than mine)
5. If no peer is closer, routing has failed (local minimum)
### Path-Broken Recovery
Greedy routing can fail if the destination has moved or the cached coordinates
are stale. When this happens, the node that cannot make progress sends a
PathBroken notification back to the source. The source then initiates a fresh
bloom filter lookup to find the destination's current coordinates.
### Session Establishment
For efficiency, FIPS establishes routing sessions that cache coordinate
information at intermediate routers. The first packet (SessionSetup) carries
full coordinates; subsequent packets use cached state for minimal overhead.
See [fips-routing.md](fips-routing.md) for the complete routing design and
[fips-session-protocol.md](fips-session-protocol.md) for session establishment.
---
## Transport Abstraction
FIPS is transport-agnostic. The protocol operates identically whether peers
connect over UDP, Ethernet, LoRa radio, serial cables, or Tor hidden services.
### Transports and Links
A **transport** is a physical or logical interface: a UDP socket, an Ethernet
NIC, a Tor client, a radio modem. A **link** is a connection instance to a
specific peer over a transport.
```
┌─────────────────────────────────────────┐
│ FIPS Node │
│ ┌─────────────────────────────────┐ │
│ │ Router Core │ │
│ └──────────┬──────────┬───────────┘ │
│ │ │ │
│ ┌──────┴────┐ ┌───┴─────┐ │
│ │ UDP │ │ LoRa │ │
│ │ Transport │ │Transport│ │
│ └────┬──────┘ └────┬────┘ │
└───────────┼─────────────┼──────────────┘
│ │
┌────┴────┐ ┌─────┴────┐
│Internet │ │ Radio │
│ Peers │ │ Peers │
└─────────┘ └──────────┘
```
### Multi-Transport Bridging
A node with multiple transports automatically bridges between networks. Peers
from all transports feed into a single spanning tree; the router selects the
best path regardless of transport type. If one transport fails, traffic
automatically routes through alternatives.
### Transport Types
| Category | Examples | Characteristics |
|----------|----------|-----------------|
| Overlay | UDP/IP, TCP/TLS, QUIC, WebSocket | Internet connectivity, NAT considerations |
| Shared medium | Ethernet, WiFi, Bluetooth, LoRa | Broadcast/multicast discovery |
| Point-to-point | Serial, dialup | No discovery needed, static config |
| Anonymity | Tor, I2P | High latency, strong privacy |
UDP over IP is expected to be the most common transport for internet-connected
nodes. Radio transports enable connectivity where internet infrastructure is
unavailable.
See [fips-transports.md](fips-transports.md) for transport characteristics.
---
## Protocol Messages
FIPS uses a discriminator-based wire format for efficient message dispatch.
### Link Layer Messages
Exchanged between directly connected peers, encrypted with link session keys:
| Type | Name | Purpose |
|------|----------------|--------------------------------------------|
| 0x10 | TreeAnnounce | Spanning tree state (parent, ancestry) |
| 0x11 | FilterAnnounce | Bloom filter reachability update |
| 0x12 | LookupRequest | Query for node's tree coordinates |
| 0x13 | LookupResponse | Response with coordinates and proof |
| 0x40 | SessionDatagram| Carries end-to-end encrypted payloads |
### Session Layer Messages
Carried inside SessionDatagram, encrypted end-to-end between source and
destination:
| Type | Name | Purpose |
|------|----------------|--------------------------------------------|
| 0x00 | SessionSetup | Establish routing session with coordinates |
| 0x01 | SessionAck | Acknowledge session establishment |
| 0x10 | DataPacket | Encrypted application data (IPv6 payload) |
| 0x20 | CoordsRequired | Router cache miss—need fresh coordinates |
| 0x21 | PathBroken | Greedy routing failed—need re-lookup |
See [fips-wire-protocol.md](fips-wire-protocol.md) for wire format details and
[fips-gossip-protocol.md](fips-gossip-protocol.md) for gossip message formats.
---
## Security Considerations
### Threat Model
FIPS assumes adversaries with varying capabilities:
- **Passive adversary**: Can observe traffic on links they control
- **Active adversary**: Can inject, modify, drop, or replay packets
- **Sybil adversary**: Can create many node identities
### Cryptographic Protections
**Link encryption**: Every peer connection uses Noise IK, providing mutual
authentication and forward secrecy. An observer on the underlying transport
sees only encrypted packets.
**End-to-end encryption**: Session-layer Noise KK encrypts payloads between
endpoints. Intermediate routers cannot read application data.
**Signature verification**: All protocol messages (TreeAnnounce, LookupResponse)
are signed. The full ancestry chain in TreeAnnounce includes signatures from
each node, preventing forged tree positions.
**Replay protection**: Sequence numbers and timestamps on announcements.
Counter-based nonces with sliding window for encrypted packets.
### Sybil Resistance
Creating many identities is cheap, but exploiting them is constrained:
- **Discretionary peering**: Node operators choose who to peer with. An attacker
with many identities still needs real nodes to accept their connections.
- **Tree coordinate verification**: Nodes cannot claim arbitrary tree positions
without valid signed ancestry chains from real nodes
- **Rate limiting**: Handshake rate limiting constrains how fast attackers can
establish connections
### Metadata Exposure
Each entity in the network sees different information:
| Entity | Can See |
|--------|---------|
| Transport observer | Encrypted packets, timing, packet sizes |
| Direct peer | Your npub (identity), traffic volume, timing |
| Intermediate router | Source and destination node_ids, packet size |
| Destination | Your npub (identity), payload content |
Intermediate routers see node_ids, not npubs. Since node_ids are derived from
npubs via one-way SHA-256 hash, routers cannot determine the actual identities
of the endpoints they route for.
The session layer hides payload content from intermediate routers. The link
layer hides everything from passive observers on the underlying transport.
---
## Conclusion
FIPS combines these elements into a cohesive system that achieves its design
goals:
- **Self-sovereign identity** through Nostr keypairs, with node_ids providing
routing-level privacy
- **Transport agnosticism** via the transport abstraction layer, enabling the
same routing logic across UDP, Ethernet/WiFi, Tor, and other link types
- **Self-organization** through distributed spanning tree formation and bloom
filter propagation, requiring no central coordination
- **Privacy preservation** with two-layer encryption that hides payloads from
intermediate routers and hides everything from transport observers
- **Resilience** through automatic partition detection, re-election, and tree
reconvergence when the network topology changes
The result is a mesh network where nodes can find and communicate with each
other securely, regardless of the underlying transport infrastructure, while
maintaining control over their own identities and peering relationships.
---
## References
### FIPS Design Documents
| Document | Description |
|----------|-------------|
| [fips-session-protocol.md](fips-session-protocol.md) | End-to-end session flow, Noise KK encryption |
| [fips-wire-protocol.md](fips-wire-protocol.md) | Link-layer transport, Noise IK handshake |
| [fips-gossip-protocol.md](fips-gossip-protocol.md) | TreeAnnounce, FilterAnnounce, Lookup formats |
| [fips-routing.md](fips-routing.md) | Bloom filters, discovery, greedy routing |
| [spanning-tree-dynamics.md](spanning-tree-dynamics.md) | Tree protocol dynamics and convergence |
| [fips-transports.md](fips-transports.md) | Transport protocol characteristics |
| [fips-architecture.md](fips-architecture.md) | Software architecture, configuration |
### External References
- [Yggdrasil Network](https://yggdrasil-network.github.io/)
- [Yggdrasil v0.5 Release Notes](https://yggdrasil-network.github.io/2023/10/22/upcoming-v05-release.html)
- [Ironwood Routing Library](https://github.com/Arceliar/ironwood)
- [Nostr Protocol](https://github.com/nostr-protocol/nips)
- [Noise Protocol Framework](https://noiseprotocol.org/)
+1 -1
View File
@@ -570,7 +570,7 @@ When nodes join/leave:
## References
- [fips-design.md](fips-design.md) — Overall FIPS architecture
- [fips-intro.md](fips-intro.md) — Overall FIPS architecture
- [fips-gossip-protocol.md](fips-gossip-protocol.md) — Wire formats for TreeAnnounce, FilterAnnounce, Lookup
- [fips-session-protocol.md](fips-session-protocol.md) — Traffic flow, crypto sessions, terminology
- [fips-wire-protocol.md](fips-wire-protocol.md) — Link-layer transport and Noise IK handshake
+2 -2
View File
@@ -80,7 +80,7 @@ Total overhead: 29 bytes (1 + 4 + 8 + 16)
- **tag**: 16-byte Poly1305 authentication tag.
The plaintext inside the encrypted frame begins with a message type byte,
followed by the message-specific payload (see fips-design.md §6 for message
followed by the message-specific payload (see fips-intro.md for message
types 0x10-0x4F).
### 2.2 Noise IK Message 1 (0x01)
@@ -790,7 +790,7 @@ protocol layers apply additional policy.
### Internal Documents
- [fips-design.md](fips-design.md) - Overall protocol design
- [fips-intro.md](fips-intro.md) - Overall protocol design
- [fips-session-protocol.md](fips-session-protocol.md) - Session establishment flow
- [fips-architecture.md](fips-architecture.md) - Software architecture
+1 -1
View File
@@ -2,7 +2,7 @@
A detailed study of the gossip-based spanning tree protocol, focusing on
operational behavior under various mesh conditions. This document complements
[fips-design.md](fips-design.md) with step-by-step walkthroughs of protocol
[fips-intro.md](fips-intro.md) with step-by-step walkthroughs of protocol
dynamics rather than message formats and data structures.
For wire formats, see [fips-gossip-protocol.md](fips-gossip-protocol.md) §2 (TreeAnnounce).