Protocol v2: X25519 handshake, sequence-number nonces, hardened transport
Red-team review of the (byte-exact) v1 port found replay, cross-session frame portability, pre-auth allocation amplification, and a symmetric key that let either peer forge as itself — flaws inherent to the v1 wire format. v2 closes them: - fixed 69-byte OVX2 hello; server validates before replying; v1 and wrong-version peers see an immediate close - HKDF(ephemeral X25519 DH, PSK, transcript) -> direction-separated session keys; forward secrecy per connection - strictly increasing u64 sequence nonces: any replay or reorder drops the connection (regression tests in tests/protocol_v2.rs) - Config: message-size cap (64 KiB default), connection semaphore, idle/body-stall/handshake/send timeouts on both roles (client-side timers retire the old no-client-timeouts quirk) - message processing inline per connection; user callbacks panic- isolated; poison-tolerant mutexes; demo key refused in release builds - PROTOCOL-V2.md supersedes PARITY-CONTRACT.md (retired, kept as port history); Cereal payload encoding is unchanged Payload serialization remains byte-exact with the original C++ (the golden scrypt/cereal vectors still govern). Zero unsafe. Verified live: server<->client handshake, encrypted echo, clean teardown. Cuts over from the C++ implementation, which is deleted (phase 5 of the port contract); it remains in the original gitea repository.
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
mod common;
|
||||
|
||||
use common::{DatagramPayload, PASSWORD, SALT, SERVER_PORT};
|
||||
use omnivox::{ConnectionContext, Decision, OmniVox, derive_encrypt_key};
|
||||
use omnivox::{Config, ConnectionContext, Decision, OmniVox, derive_encrypt_key};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex},
|
||||
@@ -18,7 +18,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.without_time()
|
||||
.init();
|
||||
|
||||
tracing::info!("Starting server on port {SERVER_PORT} with 2 threads");
|
||||
tracing::info!("Starting server on port {SERVER_PORT}");
|
||||
|
||||
let server = Arc::new(OmniVox::<DatagramPayload>::new());
|
||||
let key = derive_encrypt_key(PASSWORD.as_bytes(), SALT, 17, 8, 1)?;
|
||||
@@ -78,7 +78,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
});
|
||||
|
||||
server
|
||||
.start_server(SERVER_PORT, 2, 15000, received, disconnect, connect)
|
||||
.start_server(
|
||||
SERVER_PORT,
|
||||
Config::default(),
|
||||
received,
|
||||
disconnect,
|
||||
connect,
|
||||
)
|
||||
.await?;
|
||||
|
||||
tracing::info!("Server started successfully");
|
||||
|
||||
Reference in New Issue
Block a user