From ca93e40b170b49f98a8c379acc3ac4c33361decd Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 26 Oct 2026 23:02:12 +0100 Subject: don't leak swarm key in handshake logs --- src/transport/mod.rs | 65 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/transport/mod.rs b/src/transport/mod.rs index 3bc88e4..febbdf0 100644 --- a/src/transport/mod.rs +++ b/src/transport/mod.rs @@ -156,14 +156,8 @@ impl std::fmt::Display for BlobId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { BlobId::Change(hash) => write!(f, "change:{hash}"), - BlobId::Content(hash) => { - write!(f, "content:")?; - hash.iter().try_for_each(|byte| write!(f, "{byte:02x}")) - } - BlobId::Delta(id) => { - write!(f, "delta:")?; - id.iter().try_for_each(|byte| write!(f, "{byte:02x}")) - } + BlobId::Content(hash) => write!(f, "content:{}", Hex(hash)), + BlobId::Delta(id) => write!(f, "delta:{}", Hex(id)), } } } @@ -280,7 +274,7 @@ impl ParsedMessage { } } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub(crate) struct HelloRequest { /// The sender's swarm, if it knows it (a new node doesn't yet). A receiver in /// another swarm doesn't answer. @@ -303,7 +297,7 @@ pub(crate) struct HelloRequest { pub(crate) handshake: u32, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Clone, Serialize, Deserialize)] pub(crate) struct HelloReply { pub(crate) swarm_id: String, pub(crate) peers: Vec, @@ -328,6 +322,57 @@ pub(crate) struct HelloReply { pub(crate) sender_run_id: RunId, } +/// Bytes shown as lowercase hex, e.g. run IDs in logs. +pub(crate) struct Hex<'a>(pub(crate) &'a [u8]); + +impl std::fmt::Display for Hex<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.iter().try_for_each(|byte| write!(f, "{byte:02x}")) + } +} + +impl std::fmt::Debug for Hex<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + +/// Whether a handshake carries a swarm-key proof, not the proof: logged messages don't +/// hand out tags, and stay short. +fn auth_shown(auth: &[u8]) -> &'static str { + if auth.is_empty() { "none" } else { "present" } +} + +impl std::fmt::Debug for HelloRequest { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HelloRequest") + .field("swarm_id", &self.swarm_id) + .field("epoch", &self.epoch) + .field("epoch_seq", &self.epoch_seq) + .field("auth", &auth_shown(&self.auth)) + .field("ready", &self.ready) + .field("run_id", &Hex(&self.run_id)) + .field("handshake", &self.handshake) + .finish() + } +} + +impl std::fmt::Debug for HelloReply { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HelloReply") + .field("swarm_id", &self.swarm_id) + .field("peers", &self.peers.len()) + .field("epoch", &self.epoch) + .field("epoch_seq", &self.epoch_seq) + .field("auth", &auth_shown(&self.auth)) + .field("ready", &self.ready) + .field("run_id", &Hex(&self.run_id)) + .field("away_ms", &self.away_ms) + .field("sender_run_id", &Hex(&self.sender_run_id)) + .finish() + } +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub(crate) struct SyncEnvelope { pub(crate) swarm_id: String, -- cgit v1.3.1