Wire E2E messaging: send, recv, session persistence, auto-registration
CLI client (warzone): - `warzone init` now generates pre-key bundle (1 SPK + 10 OTPKs), stores secrets in local sled DB, saves bundle for server registration - `warzone register -s <url>` registers bundle with server - `warzone send <fp> <msg> -s <url>` full E2E flow: - Auto-registers bundle on first use - Fetches recipient's pre-key bundle - Performs X3DH key exchange (first message) or uses existing session - Encrypts with Double Ratchet - Sends WireMessage envelope to server - `warzone recv -s <url>` polls and decrypts: - Handles KeyExchange messages (X3DH respond + ratchet init as Bob) - Handles Message (decrypt with existing ratchet session) - Saves session state after each decrypt Wire protocol (WireMessage enum): - KeyExchange variant: sender identity, ephemeral key, OTPK id, ratchet msg - Message variant: sender fingerprint + ratchet message Session persistence: - Ratchet state serialized with bincode, stored in sled (~/.warzone/db) - Pre-key secrets stored in sled, OTPKs consumed on use - Sessions keyed by peer fingerprint Networking (net.rs): - register_bundle, fetch_bundle, send_message, poll_messages - JSON API over HTTP, bundles serialized with bincode + base64 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ struct Cli {
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Generate a new identity (seed + keypair)
|
||||
/// Generate a new identity (seed + keypair + pre-keys)
|
||||
Init,
|
||||
/// Recover identity from BIP39 mnemonic
|
||||
Recover {
|
||||
@@ -25,6 +25,12 @@ enum Commands {
|
||||
},
|
||||
/// Show your fingerprint and public key
|
||||
Info,
|
||||
/// Register your key bundle with a server
|
||||
Register {
|
||||
/// Server URL
|
||||
#[arg(short, long, default_value = "http://localhost:7700")]
|
||||
server: String,
|
||||
},
|
||||
/// Send an encrypted message
|
||||
Send {
|
||||
/// Recipient fingerprint (e.g. a3f8:c912:44be:7d01)
|
||||
@@ -49,22 +55,30 @@ enum Commands {
|
||||
},
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
match cli.command {
|
||||
Commands::Init => cli::init::run()?,
|
||||
Commands::Recover { words } => cli::recover::run(&words.join(" "))?,
|
||||
Commands::Info => cli::info::run()?,
|
||||
Commands::Register { server } => {
|
||||
cli::init::register_with_server(&server).await?;
|
||||
}
|
||||
Commands::Send {
|
||||
recipient,
|
||||
message,
|
||||
server,
|
||||
} => {
|
||||
println!("TODO: send '{}' to {} via {}", message, recipient, server);
|
||||
// Auto-register bundle on first send
|
||||
if let Err(_) = cli::init::register_with_server(&server).await {
|
||||
eprintln!("Warning: failed to register bundle with server");
|
||||
}
|
||||
cli::send::run(&recipient, &message, &server).await?;
|
||||
}
|
||||
Commands::Recv { server } => {
|
||||
println!("TODO: poll messages from {}", server);
|
||||
cli::recv::run(&server).await?;
|
||||
}
|
||||
Commands::Chat { server } => {
|
||||
println!("TODO: launch TUI connected to {}", server);
|
||||
|
||||
Reference in New Issue
Block a user