PKI for the license server. Replies to public key exchange requests with a server-cluster side public key. 69 bytes, not too heavy.

This commit is contained in:
Herbert Wolverson committed 2023-04-14 17:52:42 +00:00
1 parent 86dabaeded
commit 403dddd1b9
6 files changed
+81 -2

No files matched your search

+1
View File
@@ -54,6 +54,7 @@ src/webusers.toml
src/lqusers.toml
src/dist
src/rust/lqos_anonymous_stats_server/anonymous.sqlite
src/rust/long_term_stats/license_server/lqkeys.bin
# Ignore Rust build artifacts
src/rust/target
+2
View File
@@ -1604,9 +1604,11 @@ name = "license_server"
version = "0.1.0"
dependencies = [
"anyhow",
"dryoc",
"env_logger",
"log",
"lqos_bus",
"once_cell",
"pgdb",
"serde",
"serde_cbor",
@@ -11,4 +11,6 @@ log = "0"
serde_cbor = "0" # For RFC8949/7409 format C binary objects
serde = { version = "1.0", features = ["derive"] }
lqos_bus = { path = "../../lqos_bus" }
pgdb = { path = "../pgdb" }
pgdb = { path = "../pgdb" }
dryoc = { version = "0.5", features = ["serde"] }
once_cell = "1"
@@ -1,4 +1,5 @@
mod server;
mod pki;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
@@ -0,0 +1,65 @@
use std::{sync::RwLock, path::Path};
use dryoc::dryocbox::*;
use lqos_bus::bincode;
use once_cell::sync::Lazy;
pub(crate) static LIBREQOS_KEYPAIR: Lazy<RwLock<KeyPair>> = Lazy::new(|| RwLock::new(generate_new_keypair()));
const KEY_PATH: &str = "lqkeys.bin"; // Store in the working directory
pub(crate) fn generate_new_keypair() -> KeyPair {
let path = Path::new(KEY_PATH);
if path.exists() {
if let Ok(bytes) = std::fs::read(path) {
if let Ok(keypair) = bincode::deserialize(&bytes) {
log::info!("Loaded keypair from {}", path.display());
return keypair;
}
}
}
let keypair = KeyPair::gen();
let bytes = bincode::serialize(&keypair).unwrap();
std::fs::write(path, bytes).unwrap();
log::info!("Generated new keypair and stored it at {}", path.display());
keypair
}
#[cfg(test)]
mod test {
use dryoc::dryocbox::*;
use lqos_bus::bincode;
#[test]
fn test_sealed_box_roundtrip() {
let sender_keypair = KeyPair::gen();
let recipient_keypair = KeyPair::gen();
let nonce = Nonce::gen();
let message = b"Once upon a time, there was a man with a dream.";
let dryocbox = DryocBox::encrypt_to_vecbox(
message,
&nonce,
&recipient_keypair.public_key,
&sender_keypair.secret_key,
)
.expect("unable to encrypt");
let sodium_box = dryocbox.to_vec();
let dryocbox = DryocBox::from_bytes(&sodium_box).expect("failed to read box");
let decrypted = dryocbox
.decrypt_to_vec(
&nonce,
&sender_keypair.public_key,
&recipient_keypair.secret_key,
)
.expect("unable to decrypt");
assert_eq!(message, decrypted.as_slice());
}
#[test]
fn test_serialize_keypair() {
let keypair = KeyPair::gen();
let serialized = bincode::serialize(&keypair).unwrap();
let deserialized : KeyPair = bincode::deserialize(&serialized).unwrap();
assert_eq!(keypair, deserialized);
}
}
@@ -7,6 +7,8 @@ use tokio::{
spawn,
};
use crate::pki::LIBREQOS_KEYPAIR;
pub async fn start() -> anyhow::Result<()> {
let listener = TcpListener::bind(":::9126").await?;
log::info!("Listening on :::9126");
@@ -33,6 +35,7 @@ pub async fn start() -> anyhow::Result<()> {
let bytes = build_reply(&reply);
match bytes {
Ok(bytes) => {
log::info!("Submitting {} bytes to network", bytes.len());
if let Err(e) = socket.write_all(&bytes).await {
log::error!("Write error: {e:?}");
}
@@ -108,7 +111,12 @@ async fn check_license(
}
}
LicenseRequest::KeyExchange { node_id, license_key, public_key } => {
Ok(LicenseReply::Denied)
log::info!("Public key exchange requested by {node_id}");
// TODO: Associate the node & license key with their key
let public_key = LIBREQOS_KEYPAIR.read().unwrap().public_key.clone();
Ok(LicenseReply::MyPublicKey { public_key })
}
}
}