Skip to content

Commit

Permalink
core/src/: Validate PeerRecord signature matching peer ID
Browse files Browse the repository at this point in the history
Co-authored-by: Marco Munizaga <git@marcopolo.io>
  • Loading branch information
mxinden and MarcoPolo committed Feb 5, 2022
1 parent ea180aa commit c49300f
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
53 changes: 53 additions & 0 deletions core/src/peer_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ impl PeerRecord {
let record = peer_record_proto::PeerRecord::decode(payload)?;

let peer_id = PeerId::from_bytes(&record.peer_id)?;

if peer_id != envelope.key.to_peer_id() {
return Err(FromEnvelopeError::MismatchedSignature);
}

let seq = record.seq;
let addresses = record
.addresses
Expand Down Expand Up @@ -126,6 +131,8 @@ pub enum FromEnvelopeError {
InvalidPeerRecord(prost::DecodeError),
/// Failed to decode the peer ID.
InvalidPeerId(multihash::Error),
/// The signer of the envelope is different than the peer id in the record.
MismatchedSignature,
/// Failed to decode a multi-address.
InvalidMultiaddr(multiaddr::Error),
}
Expand Down Expand Up @@ -162,6 +169,10 @@ impl fmt::Display for FromEnvelopeError {
write!(f, "Failed to decode bytes as PeerRecord")
}
Self::InvalidPeerId(_) => write!(f, "Failed to decode bytes as PeerId"),
Self::MismatchedSignature => write!(
f,
"The signer of the envelope is different than the peer id in the record"
),
Self::InvalidMultiaddr(_) => {
write!(f, "Failed to decode bytes as MultiAddress")
}
Expand All @@ -174,6 +185,7 @@ impl std::error::Error for FromEnvelopeError {
match self {
Self::InvalidPeerRecord(inner) => Some(inner),
Self::InvalidPeerId(inner) => Some(inner),
Self::MismatchedSignature => None,
Self::InvalidMultiaddr(inner) => Some(inner),
Self::BadPayload(inner) => Some(inner),
}
Expand All @@ -196,4 +208,45 @@ mod tests {

assert_eq!(reconstructed, record)
}

#[test]
fn mismatched_signature() {
use prost::Message;

let addr: Multiaddr = HOME.parse().unwrap();

let envelope = {
let identity_a = Keypair::generate_ed25519();
let identity_b = Keypair::generate_ed25519();

let payload = {
let record = peer_record_proto::PeerRecord {
peer_id: identity_a.public().to_peer_id().to_bytes(),
seq: 0,
addresses: vec![peer_record_proto::peer_record::AddressInfo {
multiaddr: addr.to_vec(),
}],
};

let mut buf = Vec::with_capacity(record.encoded_len());
record
.encode(&mut buf)
.expect("Vec<u8> provides capacity as needed");
buf
};

SignedEnvelope::new(
identity_b,
String::from(DOMAIN_SEP),
PAYLOAD_TYPE.as_bytes().to_vec(),
payload,
)
.unwrap()
};

assert!(matches!(
PeerRecord::from_signed_envelope(envelope),
Err(FromEnvelopeError::MismatchedSignature)
));
}
}
30 changes: 29 additions & 1 deletion core/src/signed_envelope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use unsigned_varint::encode::usize_buffer;
/// For more details see libp2p RFC0002: <https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md>
#[derive(Debug, Clone, PartialEq)]
pub struct SignedEnvelope {
key: PublicKey,
pub(crate) key: PublicKey,
payload_type: Vec<u8>,
payload: Vec<u8>,
signature: Vec<u8>,
Expand Down Expand Up @@ -201,3 +201,31 @@ impl fmt::Display for ReadPayloadError {
}

impl std::error::Error for ReadPayloadError {}

#[cfg(test)]
mod tests {
use super::*;

#[test]
pub fn test_roundtrip() {
let kp = Keypair::generate_ed25519();
let payload = "some payload".as_bytes();
let domain_separation = "domain separation".to_string();
let payload_type: Vec<u8> = "payload type".into();

let env = SignedEnvelope::new(
kp.clone(),
domain_separation.clone(),
payload_type.clone(),
payload.into(),
)
.expect("Failed to create envelope");

let actual_payload = env
.payload(domain_separation, &payload_type)
.expect("Failed to extract payload and public key");

assert_eq!(actual_payload, payload);
assert_eq!(env.key, kp.public());
}
}

0 comments on commit c49300f

Please sign in to comment.