From 8c52925496a5fde9cc6406621d6aaac8e556ece5 Mon Sep 17 00:00:00 2001 From: MF Date: Thu, 18 Jun 2026 14:41:26 +0330 Subject: [PATCH 1/5] redact pnet pre-shared key debug output --- transports/pnet/CHANGELOG.md | 3 +++ transports/pnet/src/lib.rs | 52 ++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/transports/pnet/CHANGELOG.md b/transports/pnet/CHANGELOG.md index 6817a601fcd..9a73fd97451 100644 --- a/transports/pnet/CHANGELOG.md +++ b/transports/pnet/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.27.0 +- Redact `PreSharedKey` from `Debug` output and add `PreSharedKey::to_key_file` for + explicit raw key file export. + - Raise MSRV to 1.88.0. See [PR 6273](https://github.com/libp2p/rust-libp2p/pull/6273). diff --git a/transports/pnet/src/lib.rs b/transports/pnet/src/lib.rs index f8e810d097b..ae41e8fa226 100644 --- a/transports/pnet/src/lib.rs +++ b/transports/pnet/src/lib.rs @@ -82,6 +82,11 @@ impl PreSharedKey { .expect("shake128 failed"); Fingerprint(out) } + + /// Export this key in key file format compatible with go-libp2p. + pub fn to_key_file(self) -> String { + format!("/key/swarm/psk/1.0.0/\n/base16/\n{}\n", to_hex(&self.0)) + } } fn parse_hex_key(s: &str) -> Result<[u8; KEY_SIZE], KeyParseError> { @@ -130,8 +135,8 @@ impl FromStr for PreSharedKey { impl fmt::Debug for PreSharedKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("PreSharedKey") - .field(&to_hex(&self.0)) + f.debug_struct("PreSharedKey") + .field("fingerprint", &self.fingerprint().to_string()) .finish() } } @@ -343,6 +348,19 @@ mod tests { .quickcheck(prop as fn(PreSharedKey) -> _); } + #[test] + fn psk_to_key_file_parse() { + fn prop(key: PreSharedKey) -> bool { + let text = key.to_key_file(); + text.parse::() + .map(|res| res == key) + .unwrap_or(false) + } + QuickCheck::new() + .tests(10) + .quickcheck(prop as fn(PreSharedKey) -> _); + } + #[test] fn psk_parse_failure() { use KeyParseError::*; @@ -373,4 +391,34 @@ mod tests { let actual = key.fingerprint().to_string(); assert_eq!(expected, actual); } + + #[test] + fn debug_formatting_does_not_leak_raw_psk() { + let raw_hex = "6189c5cf0b87fb800c1a9feeda73c6ab5e998db48fb9e6a978575c770ceef683"; + let key = format!("/key/swarm/psk/1.0.0/\n/base16/\n{raw_hex}") + .parse::() + .unwrap(); + let fingerprint = key.fingerprint().to_string(); + + let debug_output = format!("{key:?}"); + let config_debug_output = format!("{:?}", PnetConfig::new(key)); + + assert!(!debug_output.contains(raw_hex)); + assert!(!config_debug_output.contains(raw_hex)); + assert!(debug_output.contains(&fingerprint)); + assert!(config_debug_output.contains(&fingerprint)); + } + + #[test] + fn key_file_export_contains_raw_psk() { + let raw_hex = "6189c5cf0b87fb800c1a9feeda73c6ab5e998db48fb9e6a978575c770ceef683"; + let key = format!("/key/swarm/psk/1.0.0/\n/base16/\n{raw_hex}") + .parse::() + .unwrap(); + + let key_file = key.to_key_file(); + + assert!(key_file.contains(raw_hex)); + assert_eq!(key_file.parse::().unwrap(), key); + } } From 208cb9e532ea56fc4c50690fd5ca147d4842dbd8 Mon Sep 17 00:00:00 2001 From: MF Date: Thu, 18 Jun 2026 17:49:40 +0330 Subject: [PATCH 2/5] Clarify pnet raw key file export --- transports/pnet/src/lib.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/transports/pnet/src/lib.rs b/transports/pnet/src/lib.rs index ae41e8fa226..c7bb826c7db 100644 --- a/transports/pnet/src/lib.rs +++ b/transports/pnet/src/lib.rs @@ -83,9 +83,9 @@ impl PreSharedKey { Fingerprint(out) } - /// Export this key in key file format compatible with go-libp2p. - pub fn to_key_file(self) -> String { - format!("/key/swarm/psk/1.0.0/\n/base16/\n{}\n", to_hex(&self.0)) + /// Export the unredacted key in go-libp2p key file format. + pub fn to_key_file(&self) -> String { + self.to_string() } } @@ -141,7 +141,7 @@ impl fmt::Debug for PreSharedKey { } } -/// Dumps a PreSharedKey in key file format compatible with go-libp2p +/// Formats the unredacted key in go-libp2p key file format. impl fmt::Display for PreSharedKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "/key/swarm/psk/1.0.0/")?; @@ -421,4 +421,22 @@ mod tests { assert!(key_file.contains(raw_hex)); assert_eq!(key_file.parse::().unwrap(), key); } + + #[test] + fn key_file_export_matches_display_serialization() { + let raw_hex = "6189c5cf0b87fb800c1a9feeda73c6ab5e998db48fb9e6a978575c770ceef683"; + let key = format!("/key/swarm/psk/1.0.0/\n/base16/\n{raw_hex}") + .parse::() + .unwrap(); + + assert_eq!( + key.to_key_file(), + key.to_string(), + "to_key_file delegates to Display; if Display stops serializing raw key files, decouple to_key_file before changing this expectation" + ); + assert_eq!( + key.to_key_file(), + format!("/key/swarm/psk/1.0.0/\n/base16/\n{raw_hex}\n") + ); + } } From 1f1c1c3611a709ce423a9894ef2328b2b8a5b6f4 Mon Sep 17 00:00:00 2001 From: Software Engineer <44354927+milaforge@users.noreply.github.com> Date: Thu, 18 Jun 2026 22:04:59 +0330 Subject: [PATCH 3/5] Update transports/pnet/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Oliveira --- transports/pnet/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transports/pnet/src/lib.rs b/transports/pnet/src/lib.rs index c7bb826c7db..8f58ecd0fa1 100644 --- a/transports/pnet/src/lib.rs +++ b/transports/pnet/src/lib.rs @@ -83,7 +83,7 @@ impl PreSharedKey { Fingerprint(out) } - /// Export the unredacted key in go-libp2p key file format. + /// Export the unredacted private key. pub fn to_key_file(&self) -> String { self.to_string() } From ca0566b7ec2bc7e8c97a13141f1af84027cafa06 Mon Sep 17 00:00:00 2001 From: MF Date: Fri, 19 Jun 2026 08:08:28 +0330 Subject: [PATCH 4/5] Make pnet keyfile export explicit --- transports/pnet/src/lib.rs | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/transports/pnet/src/lib.rs b/transports/pnet/src/lib.rs index 8f58ecd0fa1..31fb3f9e052 100644 --- a/transports/pnet/src/lib.rs +++ b/transports/pnet/src/lib.rs @@ -85,7 +85,7 @@ impl PreSharedKey { /// Export the unredacted private key. pub fn to_key_file(&self) -> String { - self.to_string() + format!("/key/swarm/psk/1.0.0/\n/base16/\n{}\n", to_hex(&self.0)) } } @@ -144,9 +144,7 @@ impl fmt::Debug for PreSharedKey { /// Formats the unredacted key in go-libp2p key file format. impl fmt::Display for PreSharedKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - writeln!(f, "/key/swarm/psk/1.0.0/")?; - writeln!(f, "/base16/")?; - writeln!(f, "{}", to_hex(&self.0)) + f.write_str(&self.to_key_file()) } } @@ -421,22 +419,4 @@ mod tests { assert!(key_file.contains(raw_hex)); assert_eq!(key_file.parse::().unwrap(), key); } - - #[test] - fn key_file_export_matches_display_serialization() { - let raw_hex = "6189c5cf0b87fb800c1a9feeda73c6ab5e998db48fb9e6a978575c770ceef683"; - let key = format!("/key/swarm/psk/1.0.0/\n/base16/\n{raw_hex}") - .parse::() - .unwrap(); - - assert_eq!( - key.to_key_file(), - key.to_string(), - "to_key_file delegates to Display; if Display stops serializing raw key files, decouple to_key_file before changing this expectation" - ); - assert_eq!( - key.to_key_file(), - format!("/key/swarm/psk/1.0.0/\n/base16/\n{raw_hex}\n") - ); - } } From 4064e45e8732838272aa222d89f1198bf1618fe9 Mon Sep 17 00:00:00 2001 From: MF Date: Fri, 19 Jun 2026 08:19:56 +0330 Subject: [PATCH 5/5] Fix pnet keyfile export self convention --- transports/pnet/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/transports/pnet/src/lib.rs b/transports/pnet/src/lib.rs index 31fb3f9e052..1ca9df620dd 100644 --- a/transports/pnet/src/lib.rs +++ b/transports/pnet/src/lib.rs @@ -84,7 +84,7 @@ impl PreSharedKey { } /// Export the unredacted private key. - pub fn to_key_file(&self) -> String { + pub fn to_key_file(self) -> String { format!("/key/swarm/psk/1.0.0/\n/base16/\n{}\n", to_hex(&self.0)) } }