Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
124 changes: 124 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
@@ -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<NodeId>,
}

/// 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<KnsUpdate>),
/// 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<u8>,
},
}

/// 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<Identity>),
/// response to [`NetAction::GetPeer`]
Peer(Option<Identity>),
/// response to [`NetAction::GetName`]
Name(Option<String>),
/// 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<String>,
}

//
// Helpers
//

pub fn sign<T>(message: T) -> Result<Vec<u8>, SendError>
where
T: Into<Vec<u8>>,
{
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<T, U, V>(from: T, message: U, signature: V) -> Result<bool, SendError>
where
T: Into<Address>,
U: Into<Vec<u8>>,
V: Into<Vec<u8>>,
{
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::<NetResponse>(resp.body())
else {
return false;
};
valid
})
}