Skip to content

Commit 44d63d8

Browse files
mxindenMarcoPolo
andauthored
core/src/: Validate PeerRecord signature matching peer ID (#2491)
Co-authored-by: Marco Munizaga <[email protected]>
1 parent e6f034c commit 44d63d8

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

core/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
- Implement `Display` on `DialError`. See [PR 2456].
88

9+
- Validate PeerRecord signature matching peer ID. See [RUSTSEC-2022-0009].
10+
911
[PR 2456]: https://github.com/libp2p/rust-libp2p/pull/2456
12+
[RUSTSEC-2022-0009]: https://rustsec.org/advisories/RUSTSEC-2022-0009.html
1013

1114
# 0.31.0 [2022-01-27]
1215

core/src/peer_record.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ impl PeerRecord {
3636
let record = peer_record_proto::PeerRecord::decode(payload)?;
3737

3838
let peer_id = PeerId::from_bytes(&record.peer_id)?;
39+
40+
if peer_id != envelope.key.to_peer_id() {
41+
return Err(FromEnvelopeError::MismatchedSignature);
42+
}
43+
3944
let seq = record.seq;
4045
let addresses = record
4146
.addresses
@@ -126,6 +131,8 @@ pub enum FromEnvelopeError {
126131
InvalidPeerRecord(prost::DecodeError),
127132
/// Failed to decode the peer ID.
128133
InvalidPeerId(multihash::Error),
134+
/// The signer of the envelope is different than the peer id in the record.
135+
MismatchedSignature,
129136
/// Failed to decode a multi-address.
130137
InvalidMultiaddr(multiaddr::Error),
131138
}
@@ -162,6 +169,10 @@ impl fmt::Display for FromEnvelopeError {
162169
write!(f, "Failed to decode bytes as PeerRecord")
163170
}
164171
Self::InvalidPeerId(_) => write!(f, "Failed to decode bytes as PeerId"),
172+
Self::MismatchedSignature => write!(
173+
f,
174+
"The signer of the envelope is different than the peer id in the record"
175+
),
165176
Self::InvalidMultiaddr(_) => {
166177
write!(f, "Failed to decode bytes as MultiAddress")
167178
}
@@ -174,6 +185,7 @@ impl std::error::Error for FromEnvelopeError {
174185
match self {
175186
Self::InvalidPeerRecord(inner) => Some(inner),
176187
Self::InvalidPeerId(inner) => Some(inner),
188+
Self::MismatchedSignature => None,
177189
Self::InvalidMultiaddr(inner) => Some(inner),
178190
Self::BadPayload(inner) => Some(inner),
179191
}
@@ -196,4 +208,45 @@ mod tests {
196208

197209
assert_eq!(reconstructed, record)
198210
}
211+
212+
#[test]
213+
fn mismatched_signature() {
214+
use prost::Message;
215+
216+
let addr: Multiaddr = HOME.parse().unwrap();
217+
218+
let envelope = {
219+
let identity_a = Keypair::generate_ed25519();
220+
let identity_b = Keypair::generate_ed25519();
221+
222+
let payload = {
223+
let record = peer_record_proto::PeerRecord {
224+
peer_id: identity_a.public().to_peer_id().to_bytes(),
225+
seq: 0,
226+
addresses: vec![peer_record_proto::peer_record::AddressInfo {
227+
multiaddr: addr.to_vec(),
228+
}],
229+
};
230+
231+
let mut buf = Vec::with_capacity(record.encoded_len());
232+
record
233+
.encode(&mut buf)
234+
.expect("Vec<u8> provides capacity as needed");
235+
buf
236+
};
237+
238+
SignedEnvelope::new(
239+
identity_b,
240+
String::from(DOMAIN_SEP),
241+
PAYLOAD_TYPE.as_bytes().to_vec(),
242+
payload,
243+
)
244+
.unwrap()
245+
};
246+
247+
assert!(matches!(
248+
PeerRecord::from_signed_envelope(envelope),
249+
Err(FromEnvelopeError::MismatchedSignature)
250+
));
251+
}
199252
}

core/src/signed_envelope.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use unsigned_varint::encode::usize_buffer;
1010
/// For more details see libp2p RFC0002: <https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md>
1111
#[derive(Debug, Clone, PartialEq)]
1212
pub struct SignedEnvelope {
13-
key: PublicKey,
13+
pub(crate) key: PublicKey,
1414
payload_type: Vec<u8>,
1515
payload: Vec<u8>,
1616
signature: Vec<u8>,
@@ -201,3 +201,31 @@ impl fmt::Display for ReadPayloadError {
201201
}
202202

203203
impl std::error::Error for ReadPayloadError {}
204+
205+
#[cfg(test)]
206+
mod tests {
207+
use super::*;
208+
209+
#[test]
210+
pub fn test_roundtrip() {
211+
let kp = Keypair::generate_ed25519();
212+
let payload = "some payload".as_bytes();
213+
let domain_separation = "domain separation".to_string();
214+
let payload_type: Vec<u8> = "payload type".into();
215+
216+
let env = SignedEnvelope::new(
217+
kp.clone(),
218+
domain_separation.clone(),
219+
payload_type.clone(),
220+
payload.into(),
221+
)
222+
.expect("Failed to create envelope");
223+
224+
let actual_payload = env
225+
.payload(domain_separation, &payload_type)
226+
.expect("Failed to extract payload and public key");
227+
228+
assert_eq!(actual_payload, payload);
229+
assert_eq!(env.key, kp.public());
230+
}
231+
}

0 commit comments

Comments
 (0)