From 2c594f1f883c25954fc1ea3c2a8f72cd817eda61 Mon Sep 17 00:00:00 2001 From: dr-frmr Date: Tue, 2 Apr 2024 12:02:17 -0400 Subject: [PATCH] add `net` section to lib, used for signing and verifying sigs --- Cargo.lock | 23 ++++++++++ Cargo.toml | 1 + src/lib.rs | 3 ++ src/net.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 src/net.rs diff --git a/Cargo.lock b/Cargo.lock index 060b678..a58b4a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -856,6 +856,7 @@ dependencies = [ "http", "mime_guess", "rand", + "rmp-serde", "serde", "serde_json", "thiserror", @@ -1209,6 +1210,28 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "rmp" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +dependencies = [ + "byteorder", + "num-traits", + "paste", +] + +[[package]] +name = "rmp-serde" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "ruint" version = "1.11.1" diff --git a/Cargo.toml b/Cargo.toml index ed4c7e6..5eac1ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ http = "1.0.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rand = "0.8" +rmp-serde = "1.1.2" thiserror = "1.0" url = "2.4.1" mime_guess = "2.0" diff --git a/src/lib.rs b/src/lib.rs index 322a83c..fd57acb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,6 +33,9 @@ pub mod http; pub mod kernel_types; /// Interact with the key_value module pub mod kv; +/// Interact with the networking module +/// For configuration, debugging, and creating signatures with networking key. +pub mod net; /// Interact with the sqlite module pub mod sqlite; /// Interact with the timer runtime module. diff --git a/src/net.rs b/src/net.rs new file mode 100644 index 0000000..656e1ca --- /dev/null +++ b/src/net.rs @@ -0,0 +1,124 @@ +use crate::*; + +// +// Networking protocol types +// + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Identity { + pub name: NodeId, + pub networking_key: String, + pub ws_routing: Option<(String, u16)>, + pub allowed_routers: Vec, +} + +/// Must be parsed from message pack vector. +/// all Get actions must be sent from local process. used for debugging +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum NetAction { + /// Received from a router of ours when they have a new pending passthrough for us. + /// We should respond (if we desire) by using them to initialize a routed connection + /// with the NodeId given. + ConnectionRequest(NodeId), + /// can only receive from trusted source, for now just ourselves locally, + /// in the future could get from remote provider + KnsUpdate(KnsUpdate), + KnsBatchUpdate(Vec), + /// get a list of peers we are connected to + GetPeers, + /// get the [`Identity`] struct for a single peer + GetPeer(String), + /// get the [`NodeId`] associated with a given namehash, if any + GetName(String), + /// get a user-readable diagnostics string containing networking inforamtion + GetDiagnostics, + /// sign the attached blob payload, sign with our node's networking key. + /// **only accepted from our own node** + /// **the source [`Address`] will always be prepended to the payload** + Sign, + /// given a message in blob payload, verify the message is signed by + /// the given source. if the signer is not in our representation of + /// the PKI, will not verify. + /// **the `from` [`Address`] will always be prepended to the payload** + Verify { + from: Address, + signature: Vec, + }, +} + +/// For now, only sent in response to a ConnectionRequest. +/// Must be parsed from message pack vector +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum NetResponse { + Accepted(NodeId), + Rejected(NodeId), + /// response to [`NetAction::GetPeers`] + Peers(Vec), + /// response to [`NetAction::GetPeer`] + Peer(Option), + /// response to [`NetAction::GetName`] + Name(Option), + /// response to [`NetAction::GetDiagnostics`]. a user-readable string. + Diagnostics(String), + /// response to [`NetAction::Sign`]. contains the signature in blob + Signed, + /// response to [`NetAction::Verify`]. boolean indicates whether + /// the signature was valid or not. note that if the signer node + /// cannot be found in our representation of PKI, this will return false, + /// because we cannot find the networking public key to verify with. + Verified(bool), +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct KnsUpdate { + pub name: String, // actual username / domain name + pub owner: String, + pub node: String, // hex namehash of node + pub public_key: String, + pub ip: String, + pub port: u16, + pub routers: Vec, +} + +// +// Helpers +// + +pub fn sign(message: T) -> Result, SendError> +where + T: Into>, +{ + Request::to(("our", "net", "distro", "sys")) + .body(rmp_serde::to_vec(&NetAction::Sign).unwrap()) + .blob_bytes(message.into()) + .send_and_await_response(30) + .unwrap() + .map(|_resp| get_blob().unwrap().bytes) +} + +pub fn verify(from: T, message: U, signature: V) -> Result +where + T: Into
, + U: Into>, + V: Into>, +{ + Request::to(("our", "net", "distro", "sys")) + .body( + rmp_serde::to_vec(&NetAction::Verify { + from: from.into(), + signature: signature.into(), + }) + .unwrap(), + ) + .blob_bytes(message.into()) + .send_and_await_response(30) + .unwrap() + .map(|resp| { + let Ok(NetResponse::Verified(valid)) = + rmp_serde::from_slice::(resp.body()) + else { + return false; + }; + valid + }) +}