From 8dd45b1bfe8b8cdb69ed4a9bc611dd312781a7de Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Thu, 26 Mar 2026 22:41:26 +0400 Subject: [PATCH] Normalize fingerprints everywhere: strip colons from URLs and DB keys Client: strip colons before putting fingerprints in URL paths (colons in URLs confuse axum path matching). Server: normalize fingerprints in message routes too. All fingerprint storage and lookup is now hex-only, case-insensitive. Co-Authored-By: Claude Opus 4.6 (1M context) --- warzone/crates/warzone-client/src/net.rs | 9 ++++++--- warzone/crates/warzone-server/src/routes/messages.rs | 8 ++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/warzone/crates/warzone-client/src/net.rs b/warzone/crates/warzone-client/src/net.rs index b724eaa..a6e151b 100644 --- a/warzone/crates/warzone-client/src/net.rs +++ b/warzone/crates/warzone-client/src/net.rs @@ -59,11 +59,12 @@ impl ServerClient { /// Fetch a user's pre-key bundle from the server. pub async fn fetch_bundle(&self, fingerprint: &str) -> Result { + let fp_clean: String = fingerprint.chars().filter(|c| c.is_ascii_hexdigit()).collect(); let response = self .client .get(format!( "{}/v1/keys/{}", - self.base_url, fingerprint + self.base_url, fp_clean )) .send() .await @@ -93,10 +94,11 @@ impl ServerClient { /// Send an encrypted message to the server for delivery. pub async fn send_message(&self, to: &str, message: &[u8]) -> Result<()> { + let to_clean: String = to.chars().filter(|c| c.is_ascii_hexdigit()).collect(); self.client .post(format!("{}/v1/messages/send", self.base_url)) .json(&SendRequest { - to: to.to_string(), + to: to_clean, message: message.to_vec(), }) .send() @@ -107,11 +109,12 @@ impl ServerClient { /// Poll for messages addressed to us. pub async fn poll_messages(&self, fingerprint: &str) -> Result>> { + let fp_clean: String = fingerprint.chars().filter(|c| c.is_ascii_hexdigit()).collect(); let resp: Vec = self .client .get(format!( "{}/v1/messages/poll/{}", - self.base_url, fingerprint + self.base_url, fp_clean )) .send() .await diff --git a/warzone/crates/warzone-server/src/routes/messages.rs b/warzone/crates/warzone-server/src/routes/messages.rs index 8d3818b..89b6b65 100644 --- a/warzone/crates/warzone-server/src/routes/messages.rs +++ b/warzone/crates/warzone-server/src/routes/messages.rs @@ -21,11 +21,15 @@ struct SendRequest { message: Vec, } +fn normalize_fp(fp: &str) -> String { + fp.chars().filter(|c| c.is_ascii_hexdigit()).collect::().to_lowercase() +} + async fn send_message( State(state): State, Json(req): Json, ) -> AppResult> { - let key = format!("queue:{}", req.to); + let key = format!("queue:{}", normalize_fp(&req.to)); state.db.messages.insert( format!("{}:{}", key, uuid::Uuid::new_v4()).as_bytes(), req.message, @@ -37,7 +41,7 @@ async fn poll_messages( State(state): State, Path(fingerprint): Path, ) -> AppResult>> { - let prefix = format!("queue:{}", fingerprint); + let prefix = format!("queue:{}", normalize_fp(&fingerprint)); let mut messages = Vec::new(); for item in state.db.messages.scan_prefix(prefix.as_bytes()) { let (_, value) = item?;