1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright (c) 2024-2026 Tristan Stoltz / Luminous Dynamics
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! # xenia-wire
//!
//! PQC-sealed binary wire protocol for remote-control streams.
//!
//! **Pre-alpha.** The wire format is not yet frozen and breaking changes
//! will land between `0.1.x` releases. Do not deploy in production.
//!
//! ## What this crate provides
//!
//! - **[`Session`]** — minimal AEAD session state: a current key, an
//! optional previous key with grace period for rekey, per-session
//! random `source_id` + `epoch`, monotonic nonce counter, and a
//! 64-slot sliding replay window.
//! - **[`ReplayWindow`]** — sliding-window replay protection keyed by
//! `(source_id, payload_type)`. IPsec/DTLS semantics.
//! - **[`Sealable`]** — generic bincode-based serialization contract.
//! Bring your own payload type.
//! - **[`seal`] / [`open`]** — generic functions for any `Sealable` payload.
//! - **[`seal_frame`] / [`open_frame`] / [`seal_input`] / [`open_input`]** —
//! convenience wrappers for the reference [`Frame`] + [`Input`] types.
//! Available under the default `reference-frame` feature.
//! - **[`seal_frame_lz4`] / [`open_frame_lz4`]** — LZ4-before-AEAD
//! compression variants. Available under the `lz4` feature.
//!
//! ## What this crate deliberately does NOT do
//!
//! - **No transport.** Sealed bytes are returned to the caller; the
//! caller ships them over TCP / WebSocket / QUIC / whatever.
//! - **No handshake.** Session keys arrive from somewhere else
//! (ML-KEM-768 in real deployments). Call [`Session::install_key`]
//! directly in tests or early prototypes.
//! - **No state machine.** `Session` has no lifecycle — no connecting,
//! authenticating, closing. Those are application concerns.
//! - **No domain semantics.** The reference [`Frame`] / [`Input`] types
//! carry opaque byte payloads. Implement [`Sealable`] on your own
//! types for anything real.
//!
//! ## Quick start
//!
//! ```
//! use xenia_wire::{Session, seal_frame, open_frame, Frame};
//!
//! let key = [0xAB; 32];
//! let mut sender = Session::new();
//! let mut receiver = Session::new();
//! sender.install_key(key);
//! receiver.install_key(key);
//!
//! let frame = Frame {
//! frame_id: 1,
//! timestamp_ms: 1_700_000_000_000,
//! payload: b"hello, xenia".to_vec(),
//! };
//! let sealed = seal_frame(&frame, &mut sender).unwrap();
//! let opened = open_frame(&sealed, &mut receiver).unwrap();
//! assert_eq!(opened.payload, b"hello, xenia");
//!
//! // Replaying the same bytes fails — the sliding window catches it.
//! assert!(open_frame(&sealed, &mut receiver).is_err());
//! ```
//!
//! ## Wire format
//!
//! ```text
//! envelope = nonce || ciphertext || tag
//! nonce : 12 bytes — source_id[0..6] || payload_type || epoch || seq[0..4]
//! ciphertext : len(plaintext) bytes — ChaCha20-Poly1305 encrypt(plaintext)
//! tag : 16 bytes — Poly1305 authentication tag
//! ```
//!
//! The plaintext is typically `bincode::serialize(payload)`. Under the
//! `lz4` feature the plaintext is `lz4_flex::compress_prepend_size(bincode_bytes)`.
//!
//! ## Feature flags
//!
//! | Feature | Default | Description |
//! |-------------------|---------|------------------------------------------------------|
//! | `reference-frame` | yes | Ships [`Frame`] + [`Input`] reference types. |
//! | `lz4` | no | Adds LZ4-before-AEAD variants for frame sealing. |
//!
//! ## License
//!
//! Dual-licensed under Apache-2.0 OR MIT.
pub use WireError;
pub use ;
pub use ;
pub use ;
pub use Sealable;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;