diff options
Diffstat (limited to 'docs/FOG-WIRE.md')
| -rw-r--r-- | docs/FOG-WIRE.md | 1246 |
1 files changed, 1246 insertions, 0 deletions
diff --git a/docs/FOG-WIRE.md b/docs/FOG-WIRE.md new file mode 100644 index 0000000..1f0964a --- /dev/null +++ b/docs/FOG-WIRE.md @@ -0,0 +1,1246 @@ +# FOG Wire Protocol + +Status: Draft 0.1 + +Date: 2026-08-08 + +## 1. Purpose + +This document defines `FOG-WIRE-1`, the authenticated transport protocol used +between adjacent online FOG roles. + +It refines the following baselines: + +- `FOG-THREAT-MODEL.md`, especially `TM-NET-01`, `TM-NET-03`, `TM-NET-04`, + `TM-NET-05`, `TM-NET-06`, `TM-PKI-02`, `TM-ROLE-01`, `TM-ROLE-02`, + `TM-ROLE-03`, `TM-OPS-01`, `TM-CRYPTO-01`, `TM-CRYPTO-02`, and + `TM-AVAIL-01`; +- `FOG-ARCHITECTURE.md`, especially `ARC-003`, `ARC-004`, `ARC-005`, + `ARC-006`, `ARC-007`, `ARC-008`, `ARC-009`, `IF-03`, `IF-04`, `IF-06`, + `IF-07`, `IF-08`, `IF-09`, `IF-10`, and `IF-11`; +- `FOG-PKI.md`, especially consensus-authorized profiles, endpoints, + role-specific epoch public keys, monotonic profile state, and hard expiry. + +FOG is not implemented. Requirements in this document are protocol targets, +not statements about deployed security. + +The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY describe +normative requirements in the sense of BCP 14 when they appear in uppercase. + +## 2. Scope + +`FOG-WIRE-1` owns: + +- the version-1 TCP carrier profile; +- selection of one exact consensus-authorized Noise profile; +- responder-only authentication for relay-to-entry links; +- mutual authentication for node, authority, storage, and observer links; +- binding of network, epoch, consensus, role, peer, key, and link context to + the Noise handshake; +- handshake and transport framing; +- fixed-size encrypted records and bounded logical-message fragmentation; +- command allowlists by link context and direction; +- per-record cipher-state rekey and bounded fresh handshakes; +- epoch and profile transition behavior; +- connection ownership, timeouts, backoff, overload, and failure behavior; +- key lifecycle, privacy-safe diagnostics, and conformance requirements. + +`FOG-WIRE-1` does not own: + +- message-level end-to-end encryption; +- KEMSphinx packet construction, routing, replay tags, or SURBs; +- the entry submission capsule or return rendezvous; +- storage capability semantics or replica durability; +- application acknowledgments, retries, or deduplication; +- mix delays, route selection, cover rates, or retrieval schedules; +- consensus construction or profile authorization; +- local administration, release updates, public mirror HTTP, or Composer + transfer formats. + +Noise protects one adjacent connection. It does not hide IP endpoints, TCP +connection existence, timing, direction, duration, or byte volume. It does +not replace KEMSphinx or end-to-end message encryption. + +## 3. Security Goals + +FOG-WIRE MUST provide, for one accepted connection: + +- authentication of every required online endpoint before application work; +- anonymity at the Noise identity layer for a blind relay connecting to an + entry; +- confidentiality and integrity of transport records after the handshake; +- forward secrecy to the extent supplied by the selected reviewed Noise or + PQNoise profile and correct erasure of ephemeral state; +- exact authorization of role adjacency and command direction; +- authenticated agreement on the network, epoch, consensus, profile, roles, + node identifiers, and transport-key identifiers; +- no silent suite, pattern, carrier, role, or version downgrade; +- fixed ciphertext length for records within one profile; +- bounded parsing, allocation, reassembly, cryptographic work, and queues; +- coarse non-amplifying remote failures; +- deterministic profile and epoch retirement. + +FOG-WIRE does not provide: + +- anonymity against an observer who can correlate connection timing or + volume; +- protocol camouflage or censorship resistance; +- authentication of a blind relay as a stable user or network identity; +- application-message authenticity or recipient authentication; +- KEMSphinx replay protection; +- delivery, liveness, or availability against sustained denial of service; +- safe operation after compromise of both endpoint processes; +- post-quantum security merely because one profile contains a post-quantum + primitive. + +## 4. Protocol Invariants + +### WIRE-INV-01: One authenticated profile + +Every connection uses exactly one immutable wire profile authorized by the +accepted consensus. Peers MUST NOT negotiate a list, guess a profile, or fall +back after failure. + +### WIRE-INV-02: One link context + +Every connection has exactly one link context that fixes the initiator role, +responder role, authentication mode, permitted direction, and command +allowlist. + +### WIRE-INV-03: No early application data + +Every Noise handshake payload is empty in version 1. No FOG command is sent, +accepted, buffered as trusted, or acted upon before the handshake completes +and peer authorization succeeds. Session resumption, PSK resumption, and +0-RTT application data are forbidden. + +### WIRE-INV-04: Consensus is the authority + +Operator configuration MAY restrict peers further, but MUST NOT add a peer, +role, endpoint, key, context, or profile absent from the accepted consensus or +trusted authority manifest. + +### WIRE-INV-05: Fixed encrypted records + +All post-handshake records on one connection have the exact ciphertext length +defined by its profile. Application type and semantic body length MUST NOT +change that record length. + +### WIRE-INV-06: Strict ordered state + +Version 1 runs over ordered TCP. Noise transport nonces and cipher-state +rekeys advance exactly once per successfully sent or received record. A +missing, duplicated, unauthentic, or out-of-order record terminates the +connection. + +### WIRE-INV-07: Purpose-separated keys + +Noise static keys, node identity keys, authority vote keys, KEMSphinx keys, +entry capsule keys, replica-envelope keys, message keys, queue-sealing keys, +and release keys are distinct. One key MUST NOT serve two of these purposes. + +### WIRE-INV-08: Bounded work before trust + +Preface, handshake, frame, record, fragment, connection, and queue work is +bounded before allocation proportional to attacker-controlled input. A peer +cannot request an arbitrary algorithm, record size, or reassembly budget. + +### WIRE-INV-09: Failure does not widen access + +Failure never causes plaintext transport, direct client fallback, layer +skipping, a new role edge, an older profile, a previous epoch, or a generic +RPC path. + +### WIRE-INV-10: Traffic scheduling is external but mandatory + +FOG-WIRE supplies fixed records and a padding record. The authenticated cover +profile decides when records are emitted. A local keepalive choice MUST NOT +silently replace or modify that traffic schedule. + +## 5. Terminology and Byte Order + +Terms used in this specification: + +- **wire profile**: immutable mapping from one numeric profile identifier to + an exact carrier, Noise protocol name, record geometry, limits, timers, + socket behavior, and compatible command-shape registry; +- **link context**: immutable role adjacency and directional command policy; +- **preface**: the fixed 32-byte cleartext connection header; +- **prologue**: the canonical byte string supplied to both Noise handshake + states and authenticated by the handshake transcript; +- **record**: one fixed-size plaintext structure encrypted as one Noise + transport message; +- **logical message**: one command body carried in one or more DATA records; +- **current consensus**: the accepted consensus valid for new work at the + local uncertainty interval; +- **staged consensus**: a valid future consensus that is not yet active for + new work. + +All integer fields defined directly by FOG-WIRE are unsigned and encoded in +network byte order, most significant byte first. Byte arrays have the exact +declared length. Reserved and padding bytes MUST be zero after decryption or +when transmitted in cleartext. + +TCP is a byte stream. An implementation MUST NOT assume that one write equals +one read, that one TCP segment equals one FOG frame, or that a partial read is +an error. + +## 6. Version-1 Carrier + +The only version-1 carrier is TCP as specified by RFC 9293. + +The version-1 carrier profile: + +- uses one direct TCP connection between descriptor-authorized endpoints; +- does not add TLS, DTLS, QUIC, HTTP, WebSocket, SOCKS, a service mesh, or a + proxy protocol header; +- treats IPv4 and IPv6 endpoint forms only as permitted by the active profile; +- binds the responder key through Noise rather than DNS or X.509; +- does not trust TCP source address as a cryptographic identity; +- uses no in-band carrier autodetection; +- uses no TCP urgent data; +- treats a half-close as connection termination after bounded output drain. + +A future carrier requires a new immutable wire profile and explicit profile +transition. One port MUST NOT auto-detect TCP FOG-WIRE, TLS, QUIC, or any +foreign protocol. + +FOG-WIRE has a visible fixed preface and does not claim to be +indistinguishable from unrelated network traffic. Noise ephemeral public keys +may also be fingerprintable. Deployment documentation MUST state this +residual risk. + +## 7. Wire Profile Registry + +Every `wire_profile_id` is a non-zero unsigned 32-bit integer whose meaning is +permanent. Reusing an identifier for changed bytes or behavior is forbidden. + +An exact wire profile definition contains at least: + +```text +[ + wire_profile_id, + wire_version, + carrier_id, + noise_protocol_name, + authentication_mode, + permitted_link_context_ids, + record_plaintext_size, + command_shape_registry_id, + maximum_session_records_per_direction, + maximum_session_ciphertext_bytes_per_direction, + maximum_session_age, + preface_timeout, + handshake_timeout, + fragment_timeout, + drain_timeout, + reconnect_backoff_profile_id, + socket_behavior_profile_id +] +``` + +The registry definition is part of the normative protocol release and is +identified by an immutable digest in release metadata. Consensus +`active_profile_ids` authorizes identifiers, not operator-provided profile +bodies. Implementations MUST reject an authorized identifier they do not +implement exactly. + +The profile fixes one complete Noise protocol name. Pattern, KEM or DH, +cipher, hash, hybrid combiner, key encoding, handshake message count, and +handshake message sizes are not independently negotiated. + +The initial concrete classical or hybrid post-quantum Noise names and reviewed +library remain a pre-PoC selection gate. FOG MUST use a published reviewed +construction and maintained implementation. It MUST NOT create a FOG-specific +KEM, cipher, combiner, Noise token, or handshake extension. + +## 8. Authentication Modes + +### 8.1 Entry mode + +`ENTRY-AUTH-1` has these semantics: + +- the initiator is a blind relay with no static Noise identity in the + handshake; +- the responder is an entry whose exact epoch Noise public key is known from + accepted consensus; +- the initiator authenticates the responder; +- the responder learns no stable relay identity from Noise; +- both sides use fresh handshake ephemeral state; +- all handshake payloads are empty; +- application work begins only after the complete handshake. + +A classical profile MAY realize these semantics with the Noise `NK` pattern +while mandating an empty first handshake payload. A post-quantum or hybrid +profile MUST name one reviewed equivalent construction explicitly. Support in +the abstract Noise framework is not authorization to improvise a conversion. + +The entry authenticates each later submission capsule under +`FOG-SPHINX-PROFILES`. A TCP address, client certificate, username, API token, +or reusable relay key MUST NOT become a durable FOG user identity. + +### 8.2 Mutual node mode + +`NODE-MUTUAL-1` has these semantics: + +- initiator and responder have distinct role-local static Noise keys; +- each endpoint knows the exact expected peer public key before connecting; +- each endpoint proves possession of its corresponding private key; +- both endpoints use fresh handshake ephemeral state; +- all handshake payloads are empty; +- application work begins only after complete mutual authentication. + +A classical profile MAY realize these semantics with Noise `KK`. A +post-quantum or hybrid profile MUST name a reviewed mutually authenticated +equivalent construction. The peer keys come from the same accepted consensus, +except authority wire keys, which come from root-certified authority wire-key +certificates referenced by that consensus. + +### 8.3 No optional authentication + +Version 1 has no anonymous-to-mutual upgrade, dummy identity, user password, +bearer token, client certificate, or authentication extension inside the +handshake. A link context determines one mode before parsing begins. + +## 9. Link Context Registry + +Version 1 reserves these link contexts: + +| ID | Name | Initiator | Responder | Mode | Connection use | +| --- | --- | --- | --- | --- | --- | +| 1 | `RELAY_ENTRY` | relay | entry | `ENTRY-AUTH-1` | submission and bounded return traffic | +| 2 | `ENTRY_LAYER1` | entry | layer-1 mix | `NODE-MUTUAL-1` | forward and reply KEMSphinx packets | +| 3 | `LAYER1_LAYER2` | layer-1 mix | layer-2 mix | `NODE-MUTUAL-1` | forward and reply KEMSphinx packets | +| 4 | `LAYER2_LAYER3` | layer-2 mix | layer-3 mix | `NODE-MUTUAL-1` | forward and reply KEMSphinx packets | +| 5 | `LAYER3_TERMINAL` | layer-3 mix | courier or authorized native service | `NODE-MUTUAL-1` | terminal request and anonymous reply | +| 6 | `COURIER_STORE` | courier | store | `NODE-MUTUAL-1` | bounded replica operations | +| 7 | `STORE_STORE` | lower `node_id` store | higher `node_id` store | `NODE-MUTUAL-1` | replica synchronization only | +| 8 | `NODE_AUTHORITY` | admitted node | authority | `NODE-MUTUAL-1` | descriptor submission only | +| 9 | `AUTHORITY_AUTHORITY` | lower `authority_id` | higher `authority_id` | `NODE-MUTUAL-1` | PKI protocol objects only | +| 10 | `ROLE_OBSERVER` | reporting role | observer | `NODE-MUTUAL-1` | approved aggregate reports only | + +The numeric ordering rule gives contexts 7 and 9 one canonical connector and +prevents persistent duplicate connections. Numeric comparison is over the +complete identifier bytes. + +The reply direction MAY use an already authenticated adjacency connection in +the reverse record direction. It does not authorize a new topology edge. The +packet profile determines which peer is the next authorized reply hop. + +Adding a context or changing its role pair, direction, mode, or command set +requires a new wire version or immutable profile transition. Operator +configuration cannot create a custom context. + +## 10. Peer Authorization + +Before starting a mutual handshake, each side MUST derive an expected peer +record from one accepted network view: + +```text +ExpectedPeer = ( + network_id, + epoch, + consensus_hash, + link_context_id, + local_role, + remote_role, + local_identifier, + remote_identifier, + local_wire_key_id, + remote_wire_key_id, + local_endpoint, + remote_endpoint +) +``` + +For node links, both node descriptors MUST be valid for the selected epoch, +their effective consensus roles and layers MUST match the link context, and +their Noise keys MUST have the `node Noise transport` purpose. + +For authority links, the authority identifier and dedicated wire public key +MUST validate through an `AuthorityWireKeyCertificate` signed by the matching +offline authority root. An authority vote key MUST NOT be used as a Noise +key. + +For `RELAY_ENTRY`, the relay identifier and key identifier are absent and are +encoded as all-zero values in the prologue. The entry descriptor, role, +endpoint, profile, and epoch key are still validated exactly. + +Authorization MUST be repeated before exposing a completed handshake to the +role implementation. A peer removed, suspended, revoked, reassigned, expired, +or no longer adjacent under consensus MUST NOT continue new work merely +because an old TCP connection remains open. + +## 11. Cleartext Preface + +Every connection begins with exactly one 32-byte `WirePreface`: + +```text +struct WirePreface { + byte magic[8]; // ASCII "FOGWIRE1" + uint16 wire_version; // 1 + uint32 wire_profile_id; + uint16 link_context_id; + uint64 epoch; + uint16 flags; // 0 + byte reserved[6]; // all zero +} +``` + +The preface is transmitted by the initiator and is not encrypted. The +responder MUST read all 32 bytes within the profile preface timeout and then: + +1. compare `magic` to the exact eight ASCII bytes `FOGWIRE1`; +2. require `wire_version` equal to 1; +3. require zero flags and reserved bytes; +4. require a locally implemented profile authorized for the declared epoch; +5. require the context to be permitted by that profile and listener; +6. require the declared epoch to be current or explicitly staged under + Section 23; +7. select exactly one handshake state without probing alternatives. + +The preface does not negotiate. The responder sends no selection, supported +list, retry profile, or downgrade hint. Any failure closes the TCP connection +without protocol bytes. + +## 12. Authenticated Noise Prologue + +Both peers construct the exact same byte string before initializing Noise: + +```text +WirePrologue = EncodeFixed( + "FOG-WIRE-PROLOGUE-1", + WirePreface, + network_id, + consensus_hash, + initiator_role_id, + responder_role_id, + initiator_identifier, + responder_identifier, + initiator_wire_key_id, + responder_wire_key_id +) +``` + +`EncodeFixed` is concatenation of the exact-width fields in the order shown. +The domain string is 19 ASCII bytes without a terminator. `network_id`, +`consensus_hash`, each identifier, and each key identifier use the hash output +length pinned by the trusted PKI suite. Role identifiers are unsigned 16-bit +integers. Absent relay identifier and key fields are all zero. + +No field is length-prefixed because every width is determined by the trusted +PKI suite and wire version. Implementations MUST publish byte-exact prologue +fixtures for every context. + +The complete `WirePrologue` is supplied as the Noise prologue input. It is +authenticated by the resulting handshake transcript but is not secret and is +not treated as extra key material. + +The implementation MUST retain the final Noise handshake hash as a +connection-local channel-binding value until connection teardown. It MUST NOT +log, publish, or reuse that value as a cross-session identifier. + +## 13. Handshake Framing and State Machine + +Each Noise handshake message is carried as: + +```text +struct HandshakeFrame { + uint16 noise_message_length; + byte noise_message[noise_message_length]; +} +``` + +Rules: + +- `noise_message_length` MUST be non-zero and at most 65,535; +- the profile MUST define the exact handshake message count and expected + length of every message; +- a received length different from the profile expectation terminates the + connection before proportional allocation; +- every Noise handshake payload is zero bytes; +- trailing, extra, duplicated, or out-of-order handshake frames terminate the + connection; +- the complete handshake MUST finish within the profile handshake timeout; +- a Noise parse, decapsulation, DH, AEAD, key, or authentication failure + terminates the connection; +- no application-specific error is sent during the handshake; +- ephemeral private state and incomplete cipher state are erased on success, + failure, or timeout to the extent supported by the runtime. + +The initiator state machine is: + +```text +TCP_CONNECTED + -> SEND_PREFACE + -> NOISE_HANDSHAKE + -> VERIFY_RESPONDER_OR_BOTH_PEERS + -> TRANSPORT + -> DRAIN_OR_FAIL + -> CLOSED +``` + +The responder state machine is: + +```text +TCP_ACCEPTED + -> READ_AND_VALIDATE_PREFACE + -> NOISE_HANDSHAKE + -> VERIFY_INITIATOR_IF_REQUIRED + -> TRANSPORT + -> DRAIN_OR_FAIL + -> CLOSED +``` + +There is no resumption state and no transition from a failed state back to +handshake on the same TCP connection. + +## 14. Transport Framing + +After a successful handshake, each record is carried as: + +```text +struct TransportFrame { + uint16 ciphertext_length; + byte ciphertext[ciphertext_length]; +} +``` + +For one connection, `ciphertext_length` is constant and equals: + +```text +record_plaintext_size + 16 +``` + +The 16 bytes are the Noise AEAD authentication overhead. The concrete profile +MUST use a Noise cipher function with this standard overhead. + +`record_plaintext_size` MUST be a multiple of 256 between 4,096 and 65,280 +bytes inclusive. Consequently every ciphertext fits the standard Noise +65,535-byte message limit. FOG-WIRE does not adopt a larger non-standard Noise +message limit. + +A receiver MUST validate the two-byte length against the one expected +constant before allocating or reading the ciphertext. Zero, short, overlong, +or profile-mismatched lengths terminate the connection. + +TCP split and coalescing are transparent to this framing. One implementation +MUST interoperate when every framing byte arrives in a separate TCP read and +when multiple frames arrive in one read. + +## 15. Record Plaintext + +Every decrypted record has this exact layout: + +```text +struct WireRecord { + uint8 record_version; // 1 + uint8 record_type; + uint16 flags; // 0 + byte message_id[16]; + uint16 command_id; + uint16 command_version; + uint32 fragment_index; + uint32 fragment_count; + uint32 total_length; + uint16 fragment_length; + uint16 reserved; // 0 + byte fragment_and_padding[record_plaintext_size - 40]; +} +``` + +The 40-byte header is fixed. Version 1 defines: + +| `record_type` | Name | Meaning | +| --- | --- | --- | +| 0 | `PADDING` | traffic-schedule record, discarded after validation | +| 1 | `DATA` | one fragment of one allowed logical command | +| 2 | `CLOSE` | authenticated planned close or fresh-handshake rotation | + +Unknown versions, types, flags, commands, command versions, or non-zero +reserved values are critical errors and terminate the connection. + +### 15.1 Padding record + +For `PADDING`, every field after `flags`, including all payload bytes, MUST be +zero. The receiver validates and discards it. It MUST pass through the same +Noise decrypt, length check, record rekey, accounting, and aggregate metrics +path as DATA records before semantic discard. + +### 15.2 Close record + +For `CLOSE`, `command_id` is a coarse close class: + +- 0: planned normal close; +- 1: authenticated fresh-handshake or epoch rotation. + +Every other header field after `flags`, except `command_id`, and all payload +bytes MUST be zero. +Failure, authentication, parsing, overload, or authorization errors do not +send a CLOSE reason. They close the socket without protocol bytes. + +### 15.3 Data record + +For `DATA`: + +- `message_id` MUST be a fresh non-zero 16-byte value generated from the + operating-system CSPRNG and unique within the connection; +- `command_id` and `command_version` MUST be allowed for the context, + direction, role pair, epoch, and command-shape registry; +- `fragment_count` MUST be from 1 through 4,096; +- `fragment_index` MUST be less than `fragment_count`; +- `total_length` MUST be no greater than 8 MiB and within the lower + context-specific limit; +- `fragment_length` MUST be no greater than + `record_plaintext_size - 40`; +- every non-final fragment MUST fill the complete fragment capacity; +- the final fragment length MUST equal the remaining declared body length; +- `fragment_count` MUST equal the unique count implied by total length and + fragment capacity; +- unused `fragment_and_padding` bytes MUST be zero. + +Zero-length command bodies use exactly one DATA record with zero fragment +length and are valid only when the command registry explicitly permits them. + +`message_id` is a connection-local reassembly handle, not a capability, +account, authentication token, delivery identifier, storage key, or +cross-session replay defense. A narrower command protocol owns idempotency and +deduplication across reconnects. + +## 16. Logical-Message Reassembly + +A receiver MAY interleave fragments from multiple logical messages only +within all profile bounds. It MUST: + +1. authenticate and validate each complete record before reading its fields; +2. reject duplicate fragment indices and inconsistent repeated metadata; +3. avoid allocation based only on `fragment_count` or `total_length`; +4. allocate or spool incrementally within a fixed connection budget; +5. accept at most eight incomplete logical messages per connection; +6. accept at most 16 MiB of incomplete reassembly state per connection; +7. expire incomplete messages at the profile fragment timeout; +8. erase partial bodies on timeout, connection loss, parse failure, or role + rejection; +9. invoke command handling only after exact complete reassembly and final + shape validation. + +A context profile MAY lower the 8 MiB message limit, eight-message count, or +16 MiB buffer budget. It MUST NOT raise them in wire version 1. + +Implementations SHOULD stream authenticated fragments into bounded +role-local temporary storage when a command legitimately exceeds the in-memory +budget. Temporary files MUST be private to the role account, unlinked or +randomly named without peer identifiers, size-bounded, and deleted on every +terminal path. + +## 17. Command Registry and Direction + +Version 1 reserves these command families: + +| ID | Command | Body owner | +| --- | --- | --- | +| 1 | `PACKET_SUBMIT` | future `FOG-ENTRY-CAPSULE` specification | +| 2 | `PACKET_FORWARD` | `FOG-SPHINX-PROFILES` fixed KEMSphinx packet | +| 3 | `PACKET_RETURN` | `FOG-SPHINX-PROFILES` bounded relay return object | +| 256 | `REPLICA_REQUEST` | `FOG-STORAGE` | +| 257 | `REPLICA_RESPONSE` | `FOG-STORAGE` | +| 258 | `REPLICA_SYNC` | `FOG-STORAGE` | +| 512 | `DESCRIPTOR_UPLOAD` | `FOG-PKI` | +| 513 | `DESCRIPTOR_RESULT` | `FOG-PKI` | +| 514 | `AUTHORITY_OBJECT` | `FOG-PKI` | +| 768 | `AGGREGATE_REPORT` | `FOG-OBSERVABILITY` | + +The directional allowlist is: + +| Context | Initiator to responder | Responder to initiator | +| --- | --- | --- | +| `RELAY_ENTRY` | `PACKET_SUBMIT` | `PACKET_RETURN` | +| `ENTRY_LAYER1` | `PACKET_FORWARD` | `PACKET_FORWARD` | +| `LAYER1_LAYER2` | `PACKET_FORWARD` | `PACKET_FORWARD` | +| `LAYER2_LAYER3` | `PACKET_FORWARD` | `PACKET_FORWARD` | +| `LAYER3_TERMINAL` | `PACKET_FORWARD` | `PACKET_FORWARD` | +| `COURIER_STORE` | `REPLICA_REQUEST` | `REPLICA_RESPONSE` | +| `STORE_STORE` | `REPLICA_SYNC` | `REPLICA_SYNC` | +| `NODE_AUTHORITY` | `DESCRIPTOR_UPLOAD` | `DESCRIPTOR_RESULT` | +| `AUTHORITY_AUTHORITY` | `AUTHORITY_OBJECT` | `AUTHORITY_OBJECT` | +| `ROLE_OBSERVER` | `AGGREGATE_REPORT` | none | + +`PACKET_FORWARD` in the reverse record direction is permitted only when the +packet profile validates the receiving peer as the next hop of an anonymous +reply. It does not allow arbitrary reverse RPC. + +Every narrower specification MUST define exact body bytes, version, maximum +size, expected padded size class, request-to-response relation, idempotency, +semantic timeout, and behavior after reconnect. Unknown commands never reach +role code. + +There is no vendor, experimental, operator-private, or generic-RPC command +range in version 1. + +## 18. Command Shapes and Length Privacy + +The active `command_shape_registry_id` maps each allowed command to: + +- one exact logical body length; or +- a small ordered set of public padded length classes; +- an exact record count for each class; +- a context-specific maximum in-flight count; +- whether zero-length bodies are valid. + +The sender pads the semantic object inside the owning protocol before passing +it to FOG-WIRE. FOG-WIRE zero-fills only unused space in the last fixed +record. It does not invent application padding classes. + +All native KEMSphinx applications use the same `PACKET_SUBMIT`, +`PACKET_FORWARD`, and `PACKET_RETURN` shapes for an active packet profile. +`fog-drop`, `fog-mailbox`, and `fog-im` MUST NOT select distinguishable wire +sizes. + +`FOG-SPHINX-PROFILES.md` defines the exact packet and return bodies. For the +non-active `FOG-SPHINX-CANDIDATE-MLKEM768-X25519-1`, `PACKET_FORWARD` is +16,150 bytes and `PACKET_RETURN` is 10,204 bytes. These calculated candidate +lengths do not authorize the suite. A wire profile paired with it must map each +body to one deterministic fixed record count and reject any other logical +length. + +The number and timing of records remain observable. A command shape is a +declared traffic class, not perfect length hiding. The simulator and owning +protocol MUST evaluate whether a class creates an unacceptable fingerprint. + +## 19. Cipher-State Rekey + +After encrypting and queueing each complete transport record, the sender MUST +call Noise `CipherState.Rekey()` on the outbound cipher state exactly once. +After successfully authenticating, decrypting, and validating the fixed +ciphertext length of each complete record, the receiver MUST call +`CipherState.Rekey()` on the inbound cipher state exactly once before +processing the record semantically. + +If authentication fails, the receiver does not advance or retry. It destroys +both transport cipher states and closes the connection. + +Noise rekey changes the current cipher key through a one-way function and does +not reset the Noise nonce. It does not add a fresh DH or KEM secret. Therefore +it MUST NOT be described as a replacement for a fresh authenticated +handshake. + +The separate inbound and outbound cipher states are never combined and +half-duplex Noise mode is forbidden. + +## 20. Fresh Handshake and Session Limits + +A connection MUST be replaced with a completely new TCP and Noise handshake +at the earliest of: + +- the profile maximum records sent in either direction; +- the profile maximum ciphertext bytes sent in either direction; +- the profile maximum session age; +- activation of a new required epoch key or wire profile; +- peer role, topology adjacency, endpoint, key, revocation, or authorization + change; +- any uncertainty about cipher-state synchronization; +- local secret-state restoration or process restart. + +Version-1 absolute ceilings are: + +| Item | Absolute ceiling | +| --- | --- | +| records per direction per session | 2^32 | +| ciphertext bytes per direction per session | 1 TiB | +| session age | 24 hours | + +Every concrete profile MUST select lower exact values based on cipher bounds, +cover rate, connection churn, epoch schedule, and measurements. + +The connector MAY establish one authenticated replacement in parallel. It +MUST NOT send new logical messages on the replacement until the handshake and +authorization complete. The old connection drains only already admitted +messages for the profile drain timeout, then closes. + +Logical-message retry across the replacement belongs to the command owner. A +transport reconnect MUST NOT silently report application success, replay an +unknown partial command, or create a second delivery without that command's +idempotency rule. + +## 21. Connection Ownership and Multiplicity + +There is at most one active data connection for one tuple: + +```text +( + network_id, + epoch, + wire_profile_id, + link_context_id, + initiator_identifier, + responder_identifier +) +``` + +`RELAY_ENTRY` uses one relay-local connection instance in place of an +initiator identifier. A relay MAY maintain the small temporary entry set +permitted by its authenticated cover profile, but the count MUST NOT vary +immediately with one user message. + +One additional authenticated connection MAY exist only as a staged +replacement. Any other duplicate is closed after authentication without +moving work to it. + +The canonical initiator in Section 9 owns reconnect attempts. A responder +does not open a reverse substitute connection. Nodes SHOULD maintain required +adjacency connections independently of application queue occupancy when the +cover profile requires it. + +## 22. Traffic Scheduling, Padding, and Liveness + +The active cover profile specifies connection maintenance and a record-emission +schedule for each privacy-relevant context. It may choose a measured constant, +Poisson, or other reviewed schedule, but all operators in that profile use the +same authenticated parameters. + +At each scheduled emission opportunity: + +- the role sends one queued DATA record allowed by the scheduling policy; or +- it sends one PADDING record when no eligible DATA record is selected. + +DATA arrival MUST NOT cause an undeclared immediate write that bypasses the +schedule. PADDING MUST NOT be disabled locally while a profile claims traffic +normalization. + +FOG-WIRE defines no `PING` or `PONG`. TCP itself has no sufficient application +liveness guarantee. Health is inferred from authenticated traffic, socket +failure, connection age, and separate coarse loop protocols. If a deployment +enables operating-system TCP keepalive only for dead-resource cleanup, its +exact settings MUST be profile-bound and it MUST NOT be counted as cover +traffic or anonymity evidence. + +Failure of required cover generation moves the role into the degraded or stop +state defined by the cover profile. It does not switch to activity-triggered +records. + +The first matrix in `FOG-SIMULATION.md` does not select this schedule. It shows +that high packet cover can improve simple timing and intersection proxies +without supplying adequate local mixing at short mean delay. Exact record +schedules still require queue, liveness, loop, polling, reply, and load models. + +## 23. Epoch and Profile Transitions + +The preface declares one epoch. The Noise prologue binds the exact consensus +hash for that epoch. Peers MUST NOT combine a descriptor, key, topology edge, +profile, or parameter from a different consensus body. + +During an authenticated transition: + +- a listener MAY accept the current epoch and one preannounced next epoch; +- a next-epoch connection MAY complete and remain staged before `valid_after`; +- no next-epoch application work is sent or accepted before `valid_after`; +- an old profile remains usable only through its signed overlap interval; +- minimum accepted profile state prevents rollback after promotion; +- a previous epoch connection stops accepting new work at its exact boundary; +- bounded draining MUST end before key or consensus hard expiry; +- expired private keys are erased after the owning protocol's last required + grace window; +- same-epoch consensus conflict freezes new connections and new work. + +A listener chooses the exact state directly from the preface and local +accepted PKI state. It does not try current and old parsers in sequence. + +At consensus `valid_until`, new handshakes and new logical messages under that +consensus stop. Existing connections MAY only perform an explicitly specified +bounded drain that does not outlive key authorization. + +## 24. Timeouts and Reconnect Backoff + +Every concrete wire profile defines exact values for: + +- TCP connect timeout; +- 32-byte preface timeout; +- complete Noise handshake timeout; +- fixed frame read and write timeout; +- incomplete logical-message fragment timeout; +- output drain timeout; +- maximum session age; +- reconnect initial delay, multiplier, ceiling, and jitter distribution. + +Version-1 absolute maxima are: + +| Timer | Maximum | +| --- | --- | +| preface | 30 seconds | +| complete handshake | 60 seconds | +| incomplete frame | 60 seconds | +| incomplete logical message | 5 minutes | +| drain | 30 seconds | +| reconnect ceiling | 15 minutes | + +Timeouts are monotonic-duration measurements, not peer-provided wall-clock +values. A timeout closes the connection without detailed remote error. + +Reconnect uses bounded exponential backoff with CSPRNG-derived full jitter. +The attempt schedule MUST NOT use node identifiers, message identifiers, +queue length, or application type as its random seed. Immediate deterministic +fallback to another route, layer, or older profile is forbidden. + +## 25. Backpressure and Resource Limits + +Before the local PoC, every role profile MUST set lower operational limits +within these version-1 absolute bounds: + +| Resource | Absolute bound | +| --- | --- | +| accepted unauthenticated connections per listener | 1,024 | +| concurrent handshakes per listener | 256 | +| active connections per authenticated peer/context | 1 plus 1 staged | +| encrypted record plaintext | 65,280 bytes | +| logical message | 8 MiB | +| fragments per logical message | 4,096 | +| incomplete messages per connection | 8 | +| incomplete reassembly bytes per connection | 16 MiB | +| queued complete logical messages per connection | 1,024 | +| command versions accepted per command | 2 during signed transition | + +Implementations MUST also bound total process connections, file descriptors, +handshake CPU, KEM decapsulations, per-source unauthenticated attempts, queue +bytes, write backlog, temporary files, and aggregate reassembly memory. + +When a queue is full, the role follows the owning command's shedding policy. +It MUST NOT allocate without bound, skip authentication, enlarge a packet, +send an error larger than the triggering record, or route around a required +layer. + +Entry-mode abuse control MAY use coarse short-lived network-source limits and +valid entry capsules, but MUST NOT create a stable cross-entry user account. +Safe anonymous admission and rate control remain an explicit open security +decision. + +## 26. Socket Behavior + +The immutable socket behavior profile fixes at least: + +- TCP no-delay behavior; +- keepalive enablement and exact cleanup timers if used; +- send and receive buffer ceilings; +- user-space write batching; +- address-family policy; +- dual-stack binding behavior; +- connection and accept backlog limits; +- maximum pending output bytes; +- graceful close and reset behavior. + +Operators MUST NOT tune these settings independently when they affect record +timing, batching, connection duration, or public traffic claims. The initial +values require trace measurement on supported operating systems because TCP +segmentation does not preserve FOG record boundaries. + +Proxy-protocol headers, transparent proxy source metadata, TLS termination, +and service-mesh sidecars are forbidden on core FOG-WIRE listeners. A +deployment requiring a network proxy is a separate analyzed profile and trust +boundary. + +## 27. Failure Behavior + +| Condition | Remote behavior | Local behavior | +| --- | --- | --- | +| invalid or unsupported preface | close without bytes | coarse counter | +| unauthorized epoch, profile, context, role, or endpoint | close without bytes | coarse authorization class | +| handshake length or timeout failure | close without bytes | coarse handshake class | +| Noise authentication or decapsulation failure | close without bytes | one aggregate crypto-failure class | +| transport length mismatch | close without bytes | coarse frame class | +| Noise record authentication failure | close without bytes | destroy both cipher states | +| unknown or malformed record | close without bytes | coarse record class | +| forbidden command or direction | close without bytes | coarse policy class | +| reassembly bound or timeout | close without bytes | erase partial state | +| queue saturation after authentication | owning protocol's uniform bounded outcome or close | aggregate overload class | +| planned rotation | one fixed CLOSE record if schedule permits | bounded drain and fresh handshake | +| TCP loss or half-close | no protocol error | erase partial state and back off | + +Peers never receive parser offsets, expected keys, supported profiles, +consensus hashes, role policy, capacity, queue depth, or cryptographic error +details. + +The implementation is not required to make all local computation paths +constant-time with respect to public invalid framing. Cryptographic libraries +MUST provide their required side-channel protections, and remotely observable +failure behavior MUST remain non-amplifying and free of detailed oracles. + +## 28. Logging and Metrics + +FOG-WIRE MUST NOT log or export: + +- plaintext or ciphertext record bodies; +- entry capsules or KEMSphinx packets; +- `message_id`, Noise handshake hash, traffic key, ephemeral key, or private + key material; +- per-record timestamps or direction traces; +- queue contents, logical-message hashes, capabilities, or reply material; +- source IP addresses for anonymous relay-to-entry sessions in persistent + application logs; +- detailed handshake failure stages associated with one remote endpoint. + +Role-local debugging MAY use coarse enumerated failure classes in a protected +short-retention log, without input bytes or secret values. Claim-bearing +profiles disable packet and record tracing. + +Metrics are delayed aggregates over declared windows and minimum populations. +Allowed examples include total completed handshakes by context, aggregate +failure class, coarse connection age bucket, aggregate queue occupancy bucket, +and total padding-to-data ratio. The observer interface receives aggregates, +not event streams. + +## 29. Key and Secret Lifecycle + +| Key or secret | Generator | Authorized use | Lifetime and overlap | Compromise response | Backup | +| --- | --- | --- | --- | --- | --- | +| Node Noise epoch private key | owning node OS CSPRNG | one node role and authorized adjacent links | profile-bounded current key, staged next key, exact grace only | revoke key or node, stop new handshakes, rotate | no routine backup | +| Entry Noise epoch private key | entry OS CSPRNG | authenticate `RELAY_ENTRY` and authorized node links | profile-bounded current and staged next | revoke entry key, stop sessions, rotate | no routine backup | +| Authority wire private key | authority wire service OS CSPRNG or controlled ceremony | authority mutual links only | root-certified bounded interval, staged next key | root-signed revocation and replacement | SHOULD NOT restore into a concurrent service | +| Handshake ephemeral private state | connection endpoint OS CSPRNG | one Noise handshake | until handshake completion or failure | close connection, erase state | none | +| Noise transport cipher states | Noise handshake `Split()` | one direction of one connection | until close or fresh handshake | destroy connection state and reauthenticate | none | +| Reassembly message identifier | sending role OS CSPRNG | one logical message within one connection | until completion or timeout | discard partial message | none | +| Queue-sealing key | owning role local secret facility | local queued ciphertext at rest | deployment-rotated, independent of Noise | quarantine queue, rotate, discard unverifiable state | profile-specific encrypted backup | + +Static private keys MUST be readable only by the one role service that owns +them. They MUST NOT appear in environment templates, command arguments, +container images, shared volumes, logs, crash dumps, examples, test fixtures, +or support bundles. + +Best-effort zeroization is required for ephemeral, cipher-state, and partial +plaintext buffers. Documentation MUST NOT claim complete erasure where the +language runtime, allocator, kernel, swap, hibernation, or hardware cannot +guarantee it. + +## 30. Implementation Requirements + +An implementation MUST: + +- use a maintained reviewed Noise or PQNoise library; +- use the operating-system CSPRNG for static keys, ephemeral state, message + identifiers, and jitter; +- keep protocol framing separate from role command parsing; +- enforce all limits before proportional allocation; +- use checked integer arithmetic for lengths, counts, and record totals; +- reject trailing bytes and unknown-critical values; +- authenticate complete records before semantic parsing; +- prevent one role package from importing another role implementation; +- expose one typed context-specific command interface, not raw generic RPC; +- disable core dumps and secret-bearing panic or exception output; +- hold static private keys in the minimum role-local protected facility; +- destroy connection state on every authentication or synchronization error; +- keep the Composer implementation free of FOG-WIRE listeners and sockets. + +The protocol implementation MUST NOT: + +- implement cryptographic primitives or hybrid combiners locally; +- let configuration specify an arbitrary Noise protocol string; +- use a shared transport key for multiple nodes or roles; +- retry decryption with old keys or profiles; +- accept a DNS result, TCP source, or TLS certificate instead of PKI key + validation; +- expose a generic byte tunnel to applications; +- compress records or logical messages at the wire layer; +- silently fragment an over-limit command; +- persist session cipher state for resumption. + +### 30.1 Required module boundaries + +The future implementation keeps these responsibilities independently +testable: + +```text +role executable and role package + -> TCP listener or connector adapter + -> FOG-WIRE session state machine + -> profile and link-context authorization + -> pure preface, prologue, frame, record, and fragment codecs + -> reviewed Noise or PQNoise library +``` + +The pure codecs MUST be testable without opening a socket or starting a role. +The session state machine owns no role database and invokes only a typed +context-specific command boundary after complete validation. The TCP adapter +owns socket IO but does not parse role command bodies. Role handlers own +semantic commands but never access Noise cipher state or unvalidated record +bytes. + +Profile registry, framing, session, and command-shape code MUST NOT be placed +in a generic `utils` package. Role packages MUST NOT call each other to bypass +the wire contract or share one transport singleton. Separate executables are +justified by the established security and state-isolation boundaries, not by +independent feature scaling. + +## 31. Conformance and Adversarial Tests + +Before the local PoC, FOG-WIRE MUST have tests for: + +- byte-exact preface encoding and every rejected field variation; +- byte-exact prologue construction for every context and PKI hash length; +- entry responder authentication with no relay static identity; +- mutual node and authority authentication; +- wrong network, consensus, epoch, context, role, node, endpoint, key, and + profile binding; +- empty handshake payload enforcement and attempted early application data; +- handshake messages at expected, short, long, zero, and 65,535-byte bounds; +- TCP reads split at every byte boundary and coalesced across multiple frames; +- fixed ciphertext length and standard Noise maximum enforcement; +- every record type and zero-reserved or zero-padding rule; +- unknown record, command, command version, close class, and direction; +- valid single- and multi-fragment reassembly; +- duplicate, missing, reordered, inconsistent, expired, excessive, and sparse + fragments; +- exact 8 MiB, 4,096-fragment, 8-message, and 16 MiB boundaries; +- per-record outbound and inbound rekey synchronization; +- authentication failure before and after a rekey boundary; +- fresh-handshake record, byte, age, epoch, topology, and profile boundaries; +- current and next epoch staging with no early forwarding; +- old-profile retirement and rollback refusal; +- duplicate connection collision and one staged replacement; +- queue saturation, slow reads, slow writes, half-close, reset, and timeout; +- reconnect backoff and jitter bounds under repeated failure; +- listener floods and expensive-handshake concurrency limits; +- log and metrics schema rejection of prohibited fields; +- parser mutation, coverage-guided fuzzing, differential framing tests, race + tests, and allocation tests; +- firewall validation for every link context and forbidden role edge. + +Tests generate ephemeral private fixtures at runtime. Private keys MUST NOT be +committed as example or conformance data. Public canonical framing fixtures +MAY be committed when they contain no secret material. + +Independent implementations MUST consume the same public framing and +transcript-binding corpus before interoperability is claimed. + +## 32. Claim Gates + +### 32.1 Functional PoC + +The local PoC MUST demonstrate: + +- one fixed reviewed Noise profile; +- responder-only relay-to-entry and mutual node authentication; +- complete traversal of entry and three mix layers; +- fixed records, padding records, fragmentation, and strict command policy; +- per-record rekey and bounded fresh handshakes; +- current and next epoch transition; +- malformed, unauthorized, flooded, and disconnected peers; +- no multi-role key, state, account, or writable-volume sharing. + +This demonstrates functional correctness only. It does not demonstrate a +production anonymity set or global-observer resistance. + +`FOG-LOCAL-POC.md` fixes the container and network boundary for this gate. It +uses one internal pairwise network per permitted data-plane adjacency, no host +ports, and no shared role state. Its current validated plan is not a FOG-WIRE +implementation and deliberately contains no invented wire profile or port. + +### 32.2 Operator alpha + +Alpha additionally requires: + +- fixed reviewed hybrid post-quantum or explicitly documented classical + profile selection; +- interoperability between independently built endpoints; +- fuzz, race, load, fault, and side-channel review results; +- measured TCP record segmentation and timing on supported systems; +- measured handshake cost and anonymous-entry flood behavior; +- six independently operated mixes and profile-conformant cover scheduling; +- rehearsed key compromise, revocation, epoch transition, and rollback tests; +- public residual-risk documentation for visible endpoints and traffic. + +### 32.3 Production transport claims + +Production claims additionally require: + +- independent protocol and implementation review; +- reviewed library and dependency provenance; +- published concrete suite, geometry, limits, and conformance results; +- verified erasure and crash behavior within stated platform limits; +- sustained adversarial load and resource-exhaustion testing; +- evidence that profile rollout does not create persistent minority + fingerprints; +- claim wording that distinguishes link confidentiality, forward secrecy, + post-quantum assumptions, and metadata privacy. + +## 33. Requirements Traceability + +| Requirement | FOG-WIRE control | +| --- | --- | +| `TM-NET-01` | fixed records, command shapes, profile-bound scheduling, padding records | +| `TM-NET-03` | bounded retries, no bypass, cover-profile failure gate | +| `TM-NET-04` | ordered Noise nonces, no resumption, command-owned cross-session deduplication | +| `TM-NET-05` | authenticated records, strict failure, no action before validation | +| `TM-NET-06` | immutable profiles, exact context, no negotiation or autodetection | +| `TM-PKI-02` | epoch and consensus binding, monotonic profile transition, hard expiry | +| `TM-ROLE-01` | anonymous relay mode, authenticated entry, no durable relay account | +| `TM-ROLE-02` | exact layer adjacency, mutual node authentication, no layer skip | +| `TM-ROLE-03` | courier/store contexts, command separation, fixed replica shapes | +| `TM-OPS-01` | prohibited log fields, delayed aggregate metrics | +| `TM-CRYPTO-01` | purpose-separated keys, lifecycle table, fresh handshakes | +| `TM-CRYPTO-02` | consensus-authorized exact Noise name, no fallback, bounded overlap | +| `TM-AVAIL-01` | strict frame, fragment, handshake, connection, queue, and CPU bounds | +| `ARC-003` | no data-plane bypass or new failure edge | +| `ARC-004` | Noise limited to adjacent transport protection | +| `ARC-005` | peers and profiles derived from one complete accepted consensus | +| `ARC-006` | fixed records and application-independent packet commands | +| `ARC-007` | one private-key owner and one purpose | +| `ARC-008` | exact versioned framing and absolute parser limits | +| `ARC-009` | coarse non-amplifying remote failure | +| `IF-03` | authenticated bounded descriptor command | +| `IF-04` | authenticated authority object command | +| `IF-06` | anonymous relay initiator, authenticated entry, fixed submission command | +| `IF-07` | mutually authenticated exact layer adjacency | +| `IF-08` | fixed authenticated layer-3 to terminal transport | +| `IF-09` | dedicated courier/store and store/store contexts | +| `IF-10` | reverse-direction packet only over authorized adjacency | +| `IF-11` | aggregate-only observer command | + +## 34. Open Pre-Implementation Selections + +The version-1 protocol structure is fixed, but these selections block daemon +implementation: + +- the exact reviewed classical or hybrid post-quantum Noise protocol names; +- the reviewed Noise or PQNoise library and supported implementation language; +- X-Wing is the leading KEM to evaluate, but no exact FOG entry or mutual + post-quantum handshake profile is selected; +- exact `wire_profile_id` assignments and immutable registry digests; +- record plaintext size and command-shape pairings; +- fresh-handshake record, byte, and age thresholds; +- concrete timeouts, reconnect distribution, and socket behavior profile; +- lower role-specific connection, queue, CPU, and memory limits; +- packet, PKI, and observer command body specifications, plus byte-exact + `FOG-STORAGE` command-to-record mappings; +- cover-record schedules and degraded-mode thresholds from simulation; +- safe anonymous entry admission and flood-control policy; +- authority wire-key certificate rollout and revocation ceremony. + +Implementations MUST NOT resolve these selections through undocumented local +defaults. Each selected value becomes an immutable reviewed profile with test +vectors and a signed transition path. + +## 35. References + +- FOG threat model: `FOG-THREAT-MODEL.md` +- FOG architecture: `FOG-ARCHITECTURE.md` +- FOG public key infrastructure: `FOG-PKI.md` +- FOG storage protocol: `FOG-STORAGE.md` +- FOG cryptographic suite evaluation: `FOG-CRYPTO-SUITES.md` +- FOG traffic and topology simulation: `FOG-SIMULATION.md` +- FOG local Podman PoC: `FOG-LOCAL-POC.md` +- Noise Protocol Framework: + <https://noiseprotocol.org/noise.html> +- Katzenpost mix network wire protocol: + <https://katzenpost.network/docs/specs/wireprotocol/> +- Post Quantum Noise: + <https://eprint.iacr.org/2022/539> +- CFRG X-Wing KEM Internet-Draft: + <https://datatracker.ietf.org/doc/draft-connolly-cfrg-xwing-kem/> +- RFC 9293, Transmission Control Protocol: + <https://www.rfc-editor.org/rfc/rfc9293.html> +- RFC 8174, Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words: + <https://www.rfc-editor.org/rfc/rfc8174.html> + +These references inform Noise handshake semantics, standard message bounds, +rekey behavior, TCP stream framing, post-quantum construction review, and +adjacent mix-link experience. They do not make a concrete FOG profile secure +without exact selection, conformance testing, operational measurement, and +independent review. |
