Skip to content

Commit

Permalink
feat(node): check peer quotes are properly signed
Browse files Browse the repository at this point in the history
maqi committed Apr 3, 2024
1 parent abfcd0c commit e3fe440
Showing 5 changed files with 53 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions sn_networking/src/lib.rs
Original file line number Diff line number Diff line change
@@ -170,6 +170,11 @@ impl Network {
self.keypair.public().verify(msg, sig)
}

/// Returns the protobuf serialised PublicKey to allow messaging out for share.
pub fn get_pub_key(&self) -> Vec<u8> {
self.keypair.public().encode_protobuf()
}

/// Dial the given peer at the given address.
/// This function will only be called for the bootstrap nodes.
pub async fn dial(&self, addr: Multiaddr) -> Result<()> {
10 changes: 9 additions & 1 deletion sn_node/src/quote.rs
Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@ impl Node {
cost,
timestamp,
quoting_metrics: quoting_metrics.clone(),
pub_key: network.get_pub_key(),
signature,
};

@@ -104,7 +105,14 @@ pub(crate) async fn quotes_verification(network: &Network, quotes: Vec<(PeerId,
quote.timestamp + time_gap > self_quote.timestamp
};

is_same_target && is_not_self && is_not_zero_quote && is_around_same_time
let is_signed_by_the_claimed_peer =
quote.check_is_signed_by_claimed_peer(*peer_id);

is_same_target
&& is_not_self
&& is_not_zero_quote
&& is_around_same_time
&& is_signed_by_the_claimed_peer
})
.cloned()
.collect();
1 change: 1 addition & 0 deletions sn_transfers/Cargo.toml
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@ custom_debug = "~0.5.0"
dirs-next = "~2.0.0"
hex = "~0.4.3"
lazy_static = "~1.4.0"
libp2p = { version="0.53", features = ["identify", "kad"] }
rand = { version = "~0.8.5", features = ["small_rng"] }
rmp-serde = "1.1.1"
serde = { version = "1.0.133", features = [ "derive", "rc" ]}
37 changes: 37 additions & 0 deletions sn_transfers/src/wallet/data_payments.rs
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
// permissions and limitations relating to use of the SAFE Network Software.

use crate::{MainPubkey, NanoTokens, Transfer};
use libp2p::{identity::PublicKey, PeerId};
use serde::{Deserialize, Serialize};
use std::time::SystemTime;
use xor_name::XorName;
@@ -102,6 +103,9 @@ pub struct PaymentQuote {
pub timestamp: SystemTime,
/// quoting metrics being used to generate this quote
pub quoting_metrics: QuotingMetrics,
/// node's public key that can verify the signature
#[debug(skip)]
pub pub_key: Vec<u8>,
#[debug(skip)]
pub signature: QuoteSignature,
}
@@ -114,6 +118,7 @@ impl PaymentQuote {
cost: NanoTokens::zero(),
timestamp: SystemTime::now(),
quoting_metrics: Default::default(),
pub_key: vec![],
signature: vec![],
}
}
@@ -142,6 +147,37 @@ impl PaymentQuote {
bytes
}

/// Check self is signed by the claimed peer
pub fn check_is_signed_by_claimed_peer(&self, claimed_peer: PeerId) -> bool {
let pub_key = if let Ok(pub_key) = PublicKey::try_decode_protobuf(&self.pub_key) {
pub_key
} else {
error!("Cann't parse PublicKey from protobuf");
return false;
};

let self_peer_id = PeerId::from(pub_key.clone());

if self_peer_id != claimed_peer {
error!("This quote {self:?} of {self_peer_id:?} is not signed by {claimed_peer:?}");
return false;
}

let bytes = Self::bytes_for_signing(
self.content,
self.cost,
self.timestamp,
&self.quoting_metrics,
);

if !pub_key.verify(&bytes, &self.signature) {
error!("Signature is not signed by claimed pub_key");
return false;
}

true
}

/// Returns true) if the quote has not yet expired
pub fn has_expired(&self) -> bool {
let now = std::time::SystemTime::now();
@@ -160,6 +196,7 @@ impl PaymentQuote {
cost,
timestamp: SystemTime::now(),
quoting_metrics: Default::default(),
pub_key: vec![],
signature: vec![],
}
}

0 comments on commit e3fe440

Please sign in to comment.