# omnivox-rs Encrypted async TCP client-server messaging — protocol **v2**. A Rust library plus example binaries, descended from the OmniVox C++ library and hardened past it after a full red-team review of v1. - X25519 handshake on every connection → forward secrecy, session-bound keys - ChaCha20-Poly1305 with strictly increasing sequence numbers → replay-proof - Direction-separated traffic keys, fixed-size pre-auth surface - scrypt (RFC 7914) password-based key derivation; `Cereal` payload encoding (byte-exact with the original's cereal binary format) for data portability - tokio transport: connection caps, idle/stall/send timeouts, panic-isolated callbacks; zero `unsafe` **Not wire-compatible with the C++ original or v1** — by design; v1 peers are refused at the handshake. See `PROTOCOL-V2.md` for the full normative spec and `PARITY-CONTRACT.md` (retired) for the port's history. ## Usage ```rust use omnivox::{Config, Cereal, CodecError, Decision, OmniVox, derive_encrypt_key}; use std::sync::Arc; let endpoint = OmniVox::::new(); endpoint.set_encrypt_key(derive_encrypt_key(b"password", b"salt", 17, 8, 1)?); endpoint.start_server(8080, Config::default(), on_data, on_disconnect, on_connect).await?; ``` Payload types implement `Cereal` (raw little-endian fields, `u64` vector lengths — the original's serialization). Runnable demos: `examples/`. ## Security posture | v1 weakness | v2 answer | |---|---| | captured frames replay forever | strict sequence numbers; a replay kills the connection | | frames portable across connections | keys bound to per-session nonces | | 5 MiB pre-auth allocation from 8 bytes | fixed 69-byte handshake before any attacker-sized read | | one symmetric key, either peer can forge as itself | direction-separated HKDF session keys | | static key, no forward secrecy | ephemeral X25519 per connection | | no client-side timeouts | full idle/stall discipline both roles | | panicking user callback killed the read loop | callbacks panic-isolated | | demo password in every repo checkout | release builds refuse the demo key | Use random 32-byte PSKs where you can; an active attacker can grind scrypt against human passwords (PAKE planned). ## Build & test ```bash cargo test # includes attack regressions: replay, version, panic, timeouts cargo clippy --all-targets -- -D warnings cargo run --example omnivox-server # terminal 1 cargo run --example omnivox-client # terminal 2 ``` ## License GPL-3.0-or-later.