diff --git a/Cargo.lock b/Cargo.lock index 138e761..48927b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,6 +645,7 @@ dependencies = [ "hex", "once_cell", "prost", + "prost-types", "rand", "salvo", "tabled", diff --git a/Cargo.toml b/Cargo.toml index 6ceb39c..6d12eb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ ed25519-dalek = { version = "2.1.1", features = ["rand_core", "serde"] } hex = "0.4.3" once_cell = "1.19.0" prost = "0.13.1" +prost-types = "0.13.1" rand = "0.8.5" salvo = "0.70.0" tabled = "0.16.0" diff --git a/src/database.rs b/src/database.rs index 907033e..d57fa73 100644 --- a/src/database.rs +++ b/src/database.rs @@ -1,8 +1,11 @@ #![allow(dead_code)] use ed25519_dalek::{Signer, SigningKey, VerifyingKey}; use once_cell::sync::Lazy; +use rand::rngs::OsRng; use std::collections::HashMap; use std::sync::Mutex; +use std::thread; +use std::time::Duration; use std::time::SystemTime; use tabled::{Table, Tabled}; @@ -111,9 +114,28 @@ pub fn get_nodes_as_html_tabe() -> String { let pubkey = hex::encode(node_info.pubkey.as_bytes()); let age = std::time::SystemTime::now() .duration_since(node_info.updated_at) - .unwrap_or(std::time::Duration::ZERO) + .unwrap_or(Duration::ZERO) .as_secs(); output.push(OutputRow { ip, pubkey, age }); } Table::new(output).to_string() } + +pub fn cycle_keys() { + thread::spawn(|| { + let mut csprng = OsRng; + loop { + // TODO: save old private key to disk using SGX Sealing + let privkey = ed25519_dalek::SigningKey::generate(&mut csprng); + add_node( + "localhost".to_string(), + NodeInfo { + pubkey: privkey.verifying_key(), + updated_at: std::time::SystemTime::now(), + }, + ); + add_key(privkey.verifying_key(), privkey); + thread::sleep(Duration::from_secs(60)); + } + }); +} diff --git a/src/grpc.rs b/src/grpc.rs index 483ec72..5e94f4e 100644 --- a/src/grpc.rs +++ b/src/grpc.rs @@ -1,6 +1,70 @@ use crate::database; use crate::database::NodeInfo; +use challenge::key_distribution_server::{KeyDistribution, KeyDistributionServer}; +use challenge::{RemoveNodeReq, UpdateKeyReq, UpdateNodeReq}; +use ed25519_dalek::SigningKey; +use prost_types::Timestamp; use rand::rngs::OsRng; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use tonic::{transport::Server, Request, Response, Status}; + +pub mod challenge { + tonic::include_proto!("challenge"); +} + +#[derive(Debug, Default)] +pub struct MyKeyDistribution {} + +fn update_db(ip: String, privkey: String, updated_at: Option) { + let key_bytes = hex::decode(privkey).unwrap(); + let privkey = SigningKey::from_bytes(&key_bytes.as_slice().try_into().unwrap()); + let pubkey = privkey.verifying_key(); + let updated_at: std::time::SystemTime = match updated_at { + Some(ts) => { + let duration = Duration::new(ts.seconds as u64, ts.nanos as u32); + UNIX_EPOCH + .checked_add(duration) + .unwrap_or(SystemTime::now()) + } + None => SystemTime::now(), + }; + database::add_node(ip.to_string(), NodeInfo { pubkey, updated_at }); + + database::add_key(pubkey, privkey); +} + +#[tonic::async_trait] +impl KeyDistribution for MyKeyDistribution { + async fn update_key(&self, request: Request) -> Result, Status> { + let ip = request.remote_addr().unwrap().ip(); + let req = request.into_inner(); + update_db(ip.to_string(), req.keypair, req.updated_at); + Ok(Response::new(())) + } + + async fn update_node(&self, request: Request) -> Result, Status> { + let req = request.into_inner(); + update_db(req.ip, req.keypair, req.updated_at); + Ok(Response::new(())) + } + + async fn remove_node(&self, _request: Request) -> Result, Status> { + // Handle RemoveNode request + Ok(Response::new(())) + } +} + +pub async fn start() -> Result<(), Box> { + let addr = "[::1]:31373".parse().unwrap(); + let key_distribution = MyKeyDistribution::default(); + + Server::builder() + .add_service(KeyDistributionServer::new(key_distribution)) + .serve(addr) + .await?; + + Ok(()) +} pub fn add_node(ip: String) { let mut csprng = OsRng; diff --git a/src/main.rs b/src/main.rs index bf66e0d..fdc7ed6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ mod database; #[tokio::main] async fn main() { + crate::database::cycle_keys(); grpc::add_node("1.1.1.1".to_string()); grpc::add_node("1.2.3.4".to_string()); grpc::add_node("2.2.2.2".to_string());