mirror of
https://github.com/jmcorgan/fips.git
synced 2026-07-30 19:46:15 +00:00
Separate protocol layers: link vs session message types
Refactor protocol.rs to cleanly separate two protocol layers: Link layer (hop-by-hop, peer-to-peer): - LinkMessageType: TreeAnnounce, FilterAnnounce, LookupRequest, LookupResponse, SessionDatagram - New SessionDatagram struct for encapsulating session payloads Session layer (end-to-end): - SessionMessageType: SessionSetup, SessionAck, DataPacket, CoordsRequired, PathBroken Also: - Remove obsolete Hello/Challenge/Auth/AuthAck types (replaced by Noise IK) - Update all design docs for consistency with two-layer architecture - Add "Link vs Session Encryption" documentation All 219 tests pass.
This commit is contained in:
+102
-139
@@ -111,153 +111,107 @@ 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
|
||||
### Peer Authentication Protocol (Noise IK)
|
||||
|
||||
When two nodes establish a connection, they perform mutual authentication to
|
||||
verify each other's identity. This prevents impersonation attacks where an
|
||||
adversary claims to be a node it doesn't control.
|
||||
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)
|
||||
|
||||
> **Note**: This authentication protocol is not derived from Yggdrasil, which
|
||||
> relies on transport-layer security (TLS/QUIC) for identity binding. FIPS
|
||||
> requires an explicit application-layer protocol because it supports transports
|
||||
> without built-in encryption or key exchange (radio links, serial connections).
|
||||
> For initial implementation, peer authentication is always performed regardless
|
||||
> of transport capabilities; this may be optimized in future versions.
|
||||
>
|
||||
> **Terminology note**: *Peer authentication* (this section) is hop-by-hop—it
|
||||
> verifies that a direct peer is who they claim to be. This is distinct from
|
||||
> *crypto sessions* (see [fips-protocol-flow.md](fips-protocol-flow.md) §6),
|
||||
> which provide end-to-end authenticated encryption between source and
|
||||
> destination using Noise KK. Both layers are necessary: peer auth secures the
|
||||
> local link; crypto sessions secure the full path.
|
||||
> 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)
|
||||
│ │
|
||||
│───── AuthInit { a_npub, nonce_a } ─────────►│
|
||||
│ knows B's npub from config │
|
||||
│ │
|
||||
│◄──── AuthChallenge { b_npub, nonce_b, │
|
||||
│ sig_b(nonce_a | a_npub) } ─────────│
|
||||
│ │
|
||||
│───── AuthComplete { │
|
||||
│ sig_a(nonce_b | b_npub) } ────────►│
|
||||
│ │
|
||||
[A verifies B after msg 2] [B verifies A after msg 3]
|
||||
│───── msg1 (82 bytes) ──────────────────────►│
|
||||
│ e: ephemeral pubkey (33) │
|
||||
│ s: encrypted static (33+16) │
|
||||
│ │ learns A's identity
|
||||
│◄───── msg2 (33 bytes) ──────────────────────│
|
||||
│ e: ephemeral pubkey (33) │
|
||||
│ │
|
||||
▼ ▼
|
||||
Authenticated Authenticated
|
||||
Noise session established Noise session established
|
||||
(symmetric keys derived) (symmetric keys derived)
|
||||
```
|
||||
|
||||
**Protocol flow:**
|
||||
#### Cryptographic Primitives
|
||||
|
||||
1. **AuthInit**: Initiator sends its npub and a 32-byte random nonce
|
||||
2. **AuthChallenge**: Responder sends its npub, its own nonce, and a signature
|
||||
proving it controls its nsec (signing the initiator's nonce and npub)
|
||||
3. **AuthComplete**: Initiator sends a signature proving it controls its nsec
|
||||
(signing the responder's nonce and npub)
|
||||
| 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 |
|
||||
|
||||
After message 2, the initiator can verify the responder's identity. After
|
||||
message 3, the responder can verify the initiator's identity. Both nodes have
|
||||
now proven they control their claimed private keys.
|
||||
#### Crossing Connection Handling
|
||||
|
||||
### Crossing Connection Handling
|
||||
|
||||
When both nodes have each other as static peers, both may initiate authentication
|
||||
simultaneously ("crossing hellos"). This is resolved using deterministic
|
||||
tie-breaking based on npub ordering:
|
||||
When both nodes simultaneously initiate connections, a deterministic tie-breaker
|
||||
resolves which connection survives:
|
||||
|
||||
```text
|
||||
A (lower npub) B (higher npub)
|
||||
│ │
|
||||
│─── AuthInit { a_npub, nonce_a } ────────►│
|
||||
│◄── AuthInit { b_npub, nonce_b } ─────────│ (crossing)
|
||||
│ │
|
||||
A < B: ignore B's init, B > A: switch to responder,
|
||||
wait for challenge send AuthChallenge
|
||||
│ │
|
||||
│◄── AuthChallenge { b_npub, ... } ────────│
|
||||
│─── AuthComplete { ... } ────────────────►│
|
||||
│ │
|
||||
▼ ▼
|
||||
Authenticated Authenticated
|
||||
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
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
Both nodes independently reach the same conclusion without coordination.
|
||||
|
||||
- If a node receives AuthInit while its own AuthInit is pending to the same peer:
|
||||
- If local npub < remote npub: Continue as initiator, ignore incoming AuthInit
|
||||
- If local npub > remote npub: Abort own initiation, switch to responder role
|
||||
#### Post-Authentication State
|
||||
|
||||
This ensures exactly one handshake completes with minimal wasted effort.
|
||||
After the Noise handshake completes:
|
||||
|
||||
### Authentication Message Structures
|
||||
- **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
|
||||
|
||||
```rust
|
||||
struct AuthInit {
|
||||
npub: [u8; 32], // Initiator's public key (x-only)
|
||||
nonce: [u8; 32], // Random challenge
|
||||
}
|
||||
#### Link vs Session Encryption
|
||||
|
||||
struct AuthChallenge {
|
||||
npub: [u8; 32], // Responder's public key (x-only)
|
||||
nonce: [u8; 32], // Responder's challenge
|
||||
signature: [u8; 64], // sig(initiator_nonce || initiator_npub)
|
||||
}
|
||||
FIPS uses two independent encryption layers:
|
||||
|
||||
struct AuthComplete {
|
||||
signature: [u8; 64], // sig(responder_nonce || responder_npub)
|
||||
}
|
||||
```
|
||||
| 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 |
|
||||
|
||||
### Signature Construction
|
||||
A packet from A→D through B traverses:
|
||||
|
||||
Signatures are constructed with domain separation to prevent cross-protocol
|
||||
signature reuse:
|
||||
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
|
||||
|
||||
```text
|
||||
digest = SHA256("fips-peer-auth-v1" || peer_nonce || peer_npub)
|
||||
signature = schnorr_sign(nsec, digest)
|
||||
```
|
||||
|
||||
**Domain separation**: The `"fips-peer-auth-v1"` prefix ensures that signatures
|
||||
created for FIPS peer authentication cannot be replayed in other contexts (e.g.,
|
||||
a Nostr event signature or FIPS crypto session). If the authentication protocol
|
||||
is revised, the version string changes (e.g., `"fips-peer-auth-v2"`).
|
||||
|
||||
**Nonce freshness**: The 32-byte random nonce from the peer ensures that
|
||||
signatures cannot be pre-computed. Each authentication attempt requires a
|
||||
fresh signature over the peer's unique challenge.
|
||||
|
||||
**Binding to peer identity**: The signature includes the peer's npub, binding
|
||||
the response to that specific peer. This prevents relay attacks where an
|
||||
adversary forwards a challenge from one node and uses the response with another.
|
||||
|
||||
### Authentication Failure Handling
|
||||
|
||||
If authentication fails at any step:
|
||||
|
||||
- **Invalid signature**: Connection is terminated immediately
|
||||
- **Wrong npub**: The node is not who it claimed to be; terminate
|
||||
- **Expired timestamp**: Possible replay attack; terminate
|
||||
- **Timeout**: Peer did not respond in time; terminate
|
||||
|
||||
Nodes should implement rate limiting on authentication attempts to prevent
|
||||
denial-of-service attacks that exhaust computational resources through
|
||||
repeated signature verifications.
|
||||
|
||||
### Post-Authentication State
|
||||
|
||||
After successful authentication, each node stores:
|
||||
|
||||
- The peer's verified npub and derived node_id
|
||||
- The link over which the peer was authenticated
|
||||
- Timestamp of successful authentication
|
||||
|
||||
This state is used for:
|
||||
|
||||
- Routing decisions (only forward to authenticated peers)
|
||||
- TreeAnnounce signature verification (cached public key lookup)
|
||||
- Session resumption on transient disconnections (within a timeout window)
|
||||
Intermediate nodes can route but cannot read session-layer payloads.
|
||||
|
||||
---
|
||||
|
||||
@@ -627,36 +581,45 @@ A single node may have multiple transports of different types:
|
||||
|
||||
## 6. Protocol Messages
|
||||
|
||||
FIPS uses two independent message type spaces corresponding to the two protocol
|
||||
layers. Messages are exchanged over Noise-encrypted links after peer authentication.
|
||||
|
||||
### Wire Format
|
||||
|
||||
```
|
||||
```text
|
||||
┌────────┬────────┬────────────────────────────────────┐
|
||||
│ Type │ Length │ Payload │
|
||||
│ 1 byte │ 2 bytes│ Variable │
|
||||
└────────┴────────┴────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Message Types
|
||||
### Link Layer Messages (Peer-to-Peer)
|
||||
|
||||
| Type | Name | Description |
|
||||
|------|------|-------------|
|
||||
| 0x00 | Dummy | Keepalive/padding |
|
||||
| 0x01 | TreeAnnounce | Spanning tree state |
|
||||
| 0x02 | BloomUpdate | Bloom filter update |
|
||||
| 0x03 | Lookup | Destination lookup request |
|
||||
| 0x04 | LookupResponse | Coordinates for requested key |
|
||||
| 0x05 | PathBroken | Route failure notification |
|
||||
| 0x06 | SessionSetup | Routing session + crypto handshake init |
|
||||
| 0x07 | SessionAck | Routing session ack + crypto response |
|
||||
| 0x08 | CoordsRequired | Router cache miss notification |
|
||||
| 0x09 | AuthInit | Peer authentication initiation |
|
||||
| 0x0a | AuthChallenge | Peer authentication challenge + response |
|
||||
| 0x0b | AuthComplete | Peer authentication completion |
|
||||
| 0x10 | Traffic | Encrypted application data |
|
||||
| 0x11 | TrafficAck | Delivery acknowledgement |
|
||||
Exchanged between directly connected peers over Noise-encrypted links.
|
||||
Peer authentication uses Noise IK handshake (see §1) before any messages.
|
||||
|
||||
See [fips-routing.md](fips-routing.md) Part 4 for routing session details and
|
||||
[fips-protocol-flow.md](fips-protocol-flow.md) §5-6 for combined establishment.
|
||||
| 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
|
||||
|
||||
|
||||
@@ -516,62 +516,59 @@ the crypto portion.
|
||||
|
||||
---
|
||||
|
||||
## 6. Crypto Session Handshake
|
||||
## 6. Session-Layer Encryption
|
||||
|
||||
The crypto session uses the Noise Protocol Framework with secp256k1, aligning
|
||||
with Nostr's cryptographic primitives.
|
||||
FIPS uses two independent Noise Protocol handshakes at different layers:
|
||||
|
||||
### 6.1 Design Decision: Noise with secp256k1
|
||||
| Layer | Scope | Pattern | Purpose |
|
||||
|---------|-------------|----------|-------------------------------------------|
|
||||
| Link | Hop-by-hop | Noise IK | Authenticate peers, encrypt link |
|
||||
| Session | End-to-end | Noise IK | Authenticate endpoints, encrypt payload |
|
||||
|
||||
**Decision**: Use Noise Protocol Framework adapted for secp256k1.
|
||||
Both use `Noise_IK_secp256k1_ChaChaPoly_SHA256` with the same cryptographic
|
||||
primitives, but with separate keys and sessions.
|
||||
|
||||
Rationale:
|
||||
### 6.1 Why Two Layers?
|
||||
|
||||
- Well-analyzed framework with formal security proofs
|
||||
- Used successfully in WireGuard, Lightning (BOLT 8), Signal
|
||||
- Lightning Network already adapted Noise for secp256k1 (precedent)
|
||||
- Reuses Nostr's existing key infrastructure (npub/nsec)
|
||||
- Provides forward secrecy via ephemeral keys
|
||||
**Link encryption** protects against passive observers on each hop but allows
|
||||
intermediate nodes to see routing information (destination address).
|
||||
|
||||
### 6.2 Pattern Selection
|
||||
**Session encryption** protects the actual payload end-to-end. Intermediate
|
||||
nodes forward opaque ciphertext without being able to read the contents.
|
||||
|
||||
Since both parties know each other's static public key (npub) before the
|
||||
handshake begins (from DNS lookup / identity cache), the **Noise KK** pattern
|
||||
is appropriate:
|
||||
### 6.2 Session Noise Handshake
|
||||
|
||||
The session-layer Noise IK handshake is carried inside `SessionSetup`/`SessionAck`
|
||||
messages, which themselves travel through the link-encrypted channel:
|
||||
|
||||
```text
|
||||
Noise_KK_secp256k1_ChaChaPoly_SHA256
|
||||
|
||||
KK:
|
||||
-> e, es, ss
|
||||
<- e, ee, se
|
||||
Initiator knows destination npub (from DNS lookup)
|
||||
│
|
||||
▼
|
||||
SessionSetup { coords, handshake_payload: Noise IK msg1 }
|
||||
│
|
||||
▼ (travels through link-encrypted hops)
|
||||
│
|
||||
Responder processes msg1, learns initiator identity
|
||||
│
|
||||
▼
|
||||
SessionAck { coords, handshake_payload: Noise IK msg2 }
|
||||
│
|
||||
▼
|
||||
Session keys established (independent of link keys)
|
||||
```
|
||||
|
||||
**Message 1 (Initiator → Responder):**
|
||||
### 6.3 Cryptographic Primitives
|
||||
|
||||
- `e`: Initiator's ephemeral public key
|
||||
- `es`: DH(initiator_ephemeral, responder_static)
|
||||
- `ss`: DH(initiator_static, responder_static)
|
||||
Both link and session layers use the same stack:
|
||||
|
||||
**Message 2 (Responder → Initiator):**
|
||||
|
||||
- `e`: Responder's ephemeral public key
|
||||
- `ee`: DH(initiator_ephemeral, responder_ephemeral)
|
||||
- `se`: DH(responder_ephemeral, initiator_static)
|
||||
|
||||
After both messages, both parties derive identical symmetric keys for
|
||||
encryption in each direction.
|
||||
|
||||
### 6.3 Why KK (not IK or XX)
|
||||
|
||||
| Pattern | Knowledge | Messages | FIPS Fit |
|
||||
|---------|-----------|----------|----------|
|
||||
| **KK** | Both know both static keys | 1 RT | Best - we have npubs |
|
||||
| IK | Initiator knows responder | 1 RT | Works but asymmetric |
|
||||
| XX | Neither knows | 2 RT | Unnecessary overhead |
|
||||
|
||||
KK provides mutual authentication in a single round-trip since FIPS always
|
||||
knows the peer's npub before initiating (from DNS/identity cache).
|
||||
| Component | Choice | Notes |
|
||||
|----------------|---------------------|----------------------------|
|
||||
| Curve | secp256k1 | Nostr-native |
|
||||
| DH | ECDH on secp256k1 | Standard EC Diffie-Hellman |
|
||||
| Cipher | ChaCha20-Poly1305 | AEAD, same as NIP-44 |
|
||||
| Hash | SHA-256 | Nostr-native |
|
||||
| Key derivation | HKDF-SHA256 | Standard Noise KDF |
|
||||
|
||||
### 6.4 Cryptographic Primitives
|
||||
|
||||
@@ -683,11 +680,11 @@ this should be updated to reflect AEAD-only authentication.
|
||||
## 7. Peer Connection Establishment
|
||||
|
||||
Before any of the traffic flows described above can occur, nodes must establish
|
||||
authenticated peer connections. This section provides a brief overview; see
|
||||
[fips-design.md](fips-design.md) §1 for the full peer authentication protocol
|
||||
and [fips-architecture.md](fips-architecture.md) for the startup sequence.
|
||||
authenticated peer connections using Noise IK. See [fips-design.md](fips-design.md)
|
||||
§1 for full protocol details and [fips-architecture.md](fips-architecture.md)
|
||||
for the startup sequence.
|
||||
|
||||
### 7.1 Connection Flow Summary
|
||||
### 7.1 Connection Flow Summary (Noise IK)
|
||||
|
||||
**Outbound (to static peer):**
|
||||
|
||||
@@ -698,43 +695,38 @@ Config: npub + transport hint (e.g., "udp:192.168.1.1:4000")
|
||||
Create link via transport
|
||||
│
|
||||
▼
|
||||
Send AuthInit { our_npub, nonce }
|
||||
Noise IK msg1 (82 bytes): ephemeral + encrypted static key
|
||||
│
|
||||
▼
|
||||
Receive AuthChallenge { peer_npub, peer_nonce, signature }
|
||||
Receive msg2 (33 bytes): peer's ephemeral key
|
||||
│
|
||||
▼
|
||||
Verify signature, send AuthComplete { signature }
|
||||
│
|
||||
▼
|
||||
Peer authenticated → begins tree gossip
|
||||
Noise session established → link encrypted → begins tree gossip
|
||||
```
|
||||
|
||||
**Inbound (peer connects to us):**
|
||||
|
||||
```text
|
||||
Transport receives data from unknown address
|
||||
Transport receives Noise msg1 from unknown address
|
||||
│
|
||||
▼
|
||||
Receive AuthInit { peer_npub, nonce }
|
||||
Process msg1 → learn peer's identity from encrypted static key
|
||||
│
|
||||
▼
|
||||
Send AuthChallenge { our_npub, our_nonce, signature }
|
||||
Send msg2 (33 bytes): our ephemeral key
|
||||
│
|
||||
▼
|
||||
Receive AuthComplete { signature }
|
||||
│
|
||||
▼
|
||||
Verify signature → peer authenticated → begins tree gossip
|
||||
Noise session established → link encrypted → begins tree gossip
|
||||
```
|
||||
|
||||
### 7.2 Post-Authentication
|
||||
|
||||
After successful peer authentication:
|
||||
After successful Noise handshake:
|
||||
|
||||
1. **TreeAnnounce exchange**: Both peers send their current tree state
|
||||
2. **FilterAnnounce exchange**: Both peers send their bloom filters
|
||||
3. **Peer is Active**: Can now participate in routing and forwarding
|
||||
1. **Link encrypted**: All subsequent messages use AEAD encryption
|
||||
2. **TreeAnnounce exchange**: Both peers send their current tree state
|
||||
3. **FilterAnnounce exchange**: Both peers send their bloom filters
|
||||
4. **Peer is Active**: Can now participate in routing and forwarding
|
||||
|
||||
The first TreeAnnounce from a new peer may trigger parent reselection if that
|
||||
peer offers a better path to root.
|
||||
@@ -746,34 +738,36 @@ peer offers a better path to root.
|
||||
This section tracks items that need reconciliation with existing design docs
|
||||
or earlier sections of this document.
|
||||
|
||||
### 8.1 Completed Updates (Session 40)
|
||||
### 8.1 Completed Updates (Session 47)
|
||||
|
||||
| Location | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| §3.1 | ✓ Done | Updated to AEAD authentication |
|
||||
| fips-routing.md Part 4 | ✓ Done | Renamed to "Routing Session Establishment", added terminology note |
|
||||
| fips-routing.md SessionSetup/Ack | ✓ Done | Added `handshake_payload` for crypto handshake |
|
||||
| fips-design.md §7 Encryption | ✓ Done | Updated to reference Noise KK instead of NIP-44 |
|
||||
| fips-design.md §6 Messages | ✓ Done | Added SessionSetup, SessionAck, CoordsRequired types |
|
||||
| fips-design.md §1 Peer Auth | ✓ Done | Added terminology note distinguishing peer auth from crypto sessions |
|
||||
| fips-architecture.md Config | ✓ Done | Renamed to "Routing Session", added "Crypto Session" section |
|
||||
| Location | Status | Notes |
|
||||
|----------------------------------|--------|----------------------------------------------------|
|
||||
| fips-design.md §1 Peer Auth | ✓ Done | Replaced custom handshake with Noise IK |
|
||||
| fips-design.md §6 Messages | ✓ Done | Split into LinkMessageType + SessionMessageType |
|
||||
| protocol.rs | ✓ Done | Removed Hello/Challenge/Auth/AuthAck types |
|
||||
| protocol.rs | ✓ Done | Added SessionDatagram for link-layer encapsulation |
|
||||
| This document §6 | ✓ Done | Updated to two-layer Noise IK architecture |
|
||||
| This document §7 | ✓ Done | Updated connection flow for Noise IK |
|
||||
|
||||
### 8.2 Cross-References Added
|
||||
### 8.2 Previous Updates (Session 40)
|
||||
|
||||
All design docs now reference fips-protocol-flow.md in their References sections:
|
||||
|
||||
- fips-design.md
|
||||
- fips-routing.md
|
||||
- fips-architecture.md
|
||||
| Location | Status | Notes |
|
||||
|----------------------------------|--------|-----------------------------------------------------|
|
||||
| §3.1 | ✓ Done | Updated to AEAD authentication |
|
||||
| fips-routing.md Part 4 | ✓ Done | Renamed to "Routing Session Establishment" |
|
||||
| fips-routing.md SessionSetup/Ack | ✓ Done | Added `handshake_payload` for crypto handshake |
|
||||
| fips-design.md §7 Encryption | ✓ Done | Updated to reference Noise instead of NIP-44 |
|
||||
| fips-architecture.md Config | ✓ Done | Renamed to "Routing Session", added "Crypto Session"|
|
||||
|
||||
### 8.3 Design Doc Alignment Summary
|
||||
|
||||
The following decisions from this document have been propagated:
|
||||
|
||||
1. **Session terminology** (§5.4): "Routing Session" vs "Crypto Session" distinction
|
||||
1. **Two-layer architecture**: Link layer (Noise IK peer auth) and session layer
|
||||
(Noise IK end-to-end) operate independently with separate keys
|
||||
2. **Session terminology** (§5.4): "Routing Session" vs "Crypto Session" distinction
|
||||
now consistent across all docs
|
||||
2. **Combined establishment** (§5.5): SessionSetup/SessionAck carry optional
|
||||
`handshake_payload` for Noise KK handshake
|
||||
3. **Noise KK** (§6): fips-design.md encryption section updated, new config
|
||||
parameters added to fips-architecture.md
|
||||
4. **Peer auth vs crypto session**: fips-design.md §1 clarifies the distinction
|
||||
3. **Combined establishment** (§5.5): SessionSetup/SessionAck carry optional
|
||||
`handshake_payload` for session-layer Noise IK handshake
|
||||
4. **Message type split**: LinkMessageType for hop-by-hop, SessionMessageType for
|
||||
end-to-end (carried inside SessionDatagram)
|
||||
|
||||
@@ -228,8 +228,7 @@ loop {
|
||||
```text
|
||||
PeerSlot::Connecting(PeerConnection)
|
||||
│
|
||||
│ AuthInit/AuthResponse exchange
|
||||
│ Noise KK handshake
|
||||
│ Noise IK handshake (2 messages)
|
||||
▼
|
||||
PeerSlot::Active(ActivePeer)
|
||||
│
|
||||
@@ -240,13 +239,13 @@ PeerSlot::Active(ActivePeer)
|
||||
|
||||
**PeerConnection** contains:
|
||||
|
||||
- Noise handshake state (ephemeral keys, handshake hash)
|
||||
- Retry tracking (attempts, last_sent)
|
||||
- Noise IK handshake state (ephemeral keys, handshake hash)
|
||||
- Expected identity (for outbound) or discovered identity (for inbound)
|
||||
- Direction (Inbound vs Outbound)
|
||||
|
||||
**ActivePeer** contains:
|
||||
|
||||
- Session keys (for encrypt/decrypt)
|
||||
- NoiseSession (symmetric keys for encrypt/decrypt)
|
||||
- Tree position (declaration, coordinates)
|
||||
- Bloom filter (what's reachable through this peer)
|
||||
- Statistics (last_seen, link_stats)
|
||||
@@ -342,9 +341,10 @@ struct Node {
|
||||
|
||||
For inbound connections from unknown addresses:
|
||||
|
||||
1. Parse packet → extract sender's identity (in AuthInit)
|
||||
2. Create new PeerConnection
|
||||
3. Add to `peers` and `addr_to_peer`
|
||||
1. Receive Noise IK msg1 → decrypt to extract sender's static key (identity)
|
||||
2. Create new PeerConnection with discovered identity
|
||||
3. Add to `connections` (by LinkId) and `addr_to_link`
|
||||
4. After handshake completes, promote to ActivePeer (indexed by NodeId)
|
||||
|
||||
## Summary
|
||||
|
||||
|
||||
Reference in New Issue
Block a user