From e6930ad553fcd8a6e800afc21b84e0d1ebff1231 Mon Sep 17 00:00:00 2001 From: yexiyue Date: Tue, 28 Jul 2026 19:09:19 +0900 Subject: [PATCH 1/2] feat(webrtc-utils): add Fingerprint::from_sdp_format `Fingerprint` can be rendered into the RFC 4572 SDP format but not parsed back out of it, so anyone reading a fingerprint off an SDP -- an out-of-tree transport, or a test asserting against a rendered description -- has to hand-roll the hex/colon decoding. Add the inverse of `to_sdp_format`. Colons are separators and hex is case-insensitive, so both are accepted on the way in. Malformed input yields `None` rather than a truncated fingerprint: a wrong fingerprint surfaces as a DTLS handshake that fails much later, which is considerably harder to diagnose. The existing `from_sdp` test decoded the constant by hand and compared it to itself, exercising no library code; it now goes through the new method. --- misc/webrtc-utils/CHANGELOG.md | 3 ++ misc/webrtc-utils/src/fingerprint.rs | 60 ++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/misc/webrtc-utils/CHANGELOG.md b/misc/webrtc-utils/CHANGELOG.md index 600101a55e7..d793d77af2e 100644 --- a/misc/webrtc-utils/CHANGELOG.md +++ b/misc/webrtc-utils/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.5.0 +- Add `Fingerprint::from_sdp_format`, the inverse of `Fingerprint::to_sdp_format`. + See [PR XXXX](https://github.com/libp2p/rust-libp2p/pull/XXXX). + - Revert migration to `quick-protobuf`, migrate back to `prost`. See [PR 6363](https://github.com/libp2p/rust-libp2p/pull/6363). diff --git a/misc/webrtc-utils/src/fingerprint.rs b/misc/webrtc-utils/src/fingerprint.rs index c32d33d5bab..3f27946b822 100644 --- a/misc/webrtc-utils/src/fingerprint.rs +++ b/misc/webrtc-utils/src/fingerprint.rs @@ -69,6 +69,19 @@ impl Fingerprint { self.0.map(|byte| format!("{byte:02X}")).join(":") } + /// Parses a fingerprint from the format described in + /// : 32 hex-encoded bytes, optionally + /// separated by colons (`:`). Case-insensitive. + /// + /// This is the inverse of [`Fingerprint::to_sdp_format`]. Returns `None` if the input is + /// not a well-formed SHA-256 fingerprint. + pub fn from_sdp_format(sdp: &str) -> Option { + let mut digest = [0u8; 32]; + hex::decode_to_slice(sdp.replace(':', ""), &mut digest).ok()?; + + Some(Self(digest)) + } + /// Returns the algorithm used (e.g. "sha-256"). /// See pub fn algorithm(&self) -> String { @@ -101,10 +114,51 @@ mod tests { #[test] fn from_sdp() { - let mut bytes = [0; 32]; - bytes.copy_from_slice(&hex::decode(SDP_FORMAT.replace(':', "")).unwrap()); + let fp = Fingerprint::from_sdp_format(SDP_FORMAT).unwrap(); - let fp = Fingerprint::raw(bytes); assert_eq!(fp, Fingerprint::raw(REGULAR_FORMAT)); } + + #[test] + fn sdp_format_round_trips() { + let fp = Fingerprint::raw(REGULAR_FORMAT); + + assert_eq!(Fingerprint::from_sdp_format(&fp.to_sdp_format()), Some(fp)); + } + + /// Colons are separators, and hex is case-insensitive; neither carries meaning. + #[test] + fn from_sdp_accepts_lowercase_and_missing_colons() { + let expected = Fingerprint::raw(REGULAR_FORMAT); + + for accepted in [ + SDP_FORMAT.to_lowercase(), + SDP_FORMAT.replace(':', ""), + SDP_FORMAT.replace(':', "").to_lowercase(), + ] { + assert_eq!(Fingerprint::from_sdp_format(&accepted), Some(expected)); + } + } + + /// A truncated or malformed fingerprint must not yield a partial one: a wrong fingerprint + /// silently fails the DTLS handshake much later, which is far harder to diagnose. + #[test] + fn from_sdp_rejects_malformed_input() { + for rejected in [ + "", + "not hex at all", + // One byte short. + &SDP_FORMAT[..SDP_FORMAT.len() - 3], + // One byte too many. + &format!("{SDP_FORMAT}:AB"), + // Odd number of nibbles. + &SDP_FORMAT[..SDP_FORMAT.len() - 1], + ] { + assert_eq!( + Fingerprint::from_sdp_format(rejected), + None, + "should have rejected {rejected:?}" + ); + } + } } From 9ebc6017e893c090dacea91c7e2044bfcedd028c Mon Sep 17 00:00:00 2001 From: yexiyue Date: Tue, 28 Jul 2026 19:10:00 +0900 Subject: [PATCH 2/2] chore(webrtc-utils): fill in changelog PR number --- misc/webrtc-utils/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/webrtc-utils/CHANGELOG.md b/misc/webrtc-utils/CHANGELOG.md index d793d77af2e..45db847969b 100644 --- a/misc/webrtc-utils/CHANGELOG.md +++ b/misc/webrtc-utils/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.5.0 - Add `Fingerprint::from_sdp_format`, the inverse of `Fingerprint::to_sdp_format`. - See [PR XXXX](https://github.com/libp2p/rust-libp2p/pull/XXXX). + See [PR 6571](https://github.com/libp2p/rust-libp2p/pull/6571). - Revert migration to `quick-protobuf`, migrate back to `prost`. See [PR 6363](https://github.com/libp2p/rust-libp2p/pull/6363).