From 64f9c53c183d502b34da1b768ace91f4323a25f9 Mon Sep 17 00:00:00 2001 From: Alw3ys Date: Fri, 15 Dec 2023 11:26:54 +0100 Subject: [PATCH] propagate errors --- Cargo.lock | 2 ++ dosei/Cargo.toml | 2 ++ dosei/src/main.rs | 2 +- dosei/src/server.rs | 14 ++++---- dosei/src/server/secret.rs | 72 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 dosei/src/server/secret.rs diff --git a/Cargo.lock b/Cargo.lock index dc862477..91cf00f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -539,9 +539,11 @@ dependencies = [ "env_logger", "futures-util", "gcp_auth", + "hex", "log", "once_cell", "prost", + "ring 0.17.7", "serde", "serde_json", "sqlx", diff --git a/dosei/Cargo.toml b/dosei/Cargo.toml index cda4ff62..4539e364 100644 --- a/dosei/Cargo.toml +++ b/dosei/Cargo.toml @@ -29,3 +29,5 @@ anyhow = "1.0.75" once_cell = "1.19.0" futures-util = "0.3.29" gcp_auth = "0.9.0" +ring = { version = "0.17.7" } +hex = "0.4.3" diff --git a/dosei/src/main.rs b/dosei/src/main.rs index 7fc28952..db851290 100644 --- a/dosei/src/main.rs +++ b/dosei/src/main.rs @@ -7,6 +7,6 @@ use config::Config; #[tokio::main] async fn main() -> anyhow::Result<()> { let config: &'static Config = Box::leak(Box::new(config::init())); - server::start_server(config).await; + server::start_server(config).await?; Ok(()) } diff --git a/dosei/src/server.rs b/dosei/src/server.rs index a6d007ce..c994afc3 100644 --- a/dosei/src/server.rs +++ b/dosei/src/server.rs @@ -1,5 +1,6 @@ mod cluster; mod cron; +mod secret; use sqlx::postgres::Postgres; use sqlx::Pool; @@ -10,10 +11,8 @@ use crate::config::Config; use axum::{routing, Extension, Router}; use log::info; -pub async fn start_server(config: &'static Config) { - let pool = Pool::::connect(&env::var("DATABASE_URL").unwrap()) - .await - .unwrap(); +pub async fn start_server(config: &'static Config) -> anyhow::Result<()> { + let pool = Pool::::connect(&env::var("DATABASE_URL")?).await?; let shared_pool = Arc::new(pool); info!("Successfully connected to Postgres"); cluster::start_node(config); @@ -24,8 +23,9 @@ pub async fn start_server(config: &'static Config) { .layer(Extension(Arc::clone(&shared_pool))); let address = config.address.to_string(); info!("Dosei running on http://{} (Press CTRL+C to quit", address); - axum::Server::bind(&address.parse().unwrap()) + secret::encrypt_secret().unwrap(); + axum::Server::bind(&address.parse()?) .serve(app.into_make_service()) - .await - .unwrap(); + .await?; + Ok(()) } diff --git a/dosei/src/server/secret.rs b/dosei/src/server/secret.rs new file mode 100644 index 00000000..59a95136 --- /dev/null +++ b/dosei/src/server/secret.rs @@ -0,0 +1,72 @@ +use ring::rand::{SecureRandom, SystemRandom}; +use ring::aead::{Aad, AES_256_GCM, BoundKey, Nonce, NONCE_LEN, NonceSequence, OpeningKey, SealingKey, UnboundKey}; +use ring::error::Unspecified; + +struct CounterNonceSequence(u32); + +impl NonceSequence for CounterNonceSequence { + // called once for each seal operation + fn advance(&mut self) -> Result { + let mut nonce_bytes = vec![0; NONCE_LEN]; + + let bytes = self.0.to_be_bytes(); + nonce_bytes[8..].copy_from_slice(&bytes); + println!("nonce_bytes = {}", hex::encode(&nonce_bytes)); + + self.0 += 1; // advance the counter + Nonce::try_assume_unique_for_key(&nonce_bytes) + } +} + +pub fn encrypt_secret() -> Result<(), Unspecified> { + // Create a new instance of SystemRandom to be used as the single source of entropy + let rand = SystemRandom::new(); + + // Generate a new symmetric encryption key + let mut key_bytes = vec![0; AES_256_GCM.key_len()]; + rand.fill(&mut key_bytes)?; + println!("key_bytes = {}", hex::encode(&key_bytes)); // don't print this in production code + + // Create a new AEAD key without a designated role or nonce sequence + let unbound_key = UnboundKey::new(&AES_256_GCM, &key_bytes)?; + + // Create a new NonceSequence type which generates nonces + let nonce_sequence = CounterNonceSequence(1); + + // Create a new AEAD key for encrypting and signing ("sealing"), bound to a nonce sequence + // The SealingKey can be used multiple times, each time a new nonce will be used + let mut sealing_key = SealingKey::new(unbound_key, nonce_sequence); + + + // This data will be authenticated but not encrypted + //let associated_data = Aad::empty(); // is optional so can be empty + let associated_data = Aad::from(b"additional public data"); + + // Data to be encrypted + let data = b"hello world"; + println!("data = {}", String::from_utf8(data.to_vec()).unwrap()); + + // Create a mutable copy of the data that will be encrypted in place + let mut in_out = data.clone(); + + // Encrypt the data with AEAD using the AES_256_GCM algorithm + let tag = sealing_key.seal_in_place_separate_tag(associated_data, &mut in_out)?; + println!("encrypted_data = {:?} {:?}", in_out, hex::encode(&in_out)); // Print the encrypted data + + // Recreate the previously moved variables + let unbound_key = UnboundKey::new(&AES_256_GCM, &key_bytes)?; + let nonce_sequence = CounterNonceSequence(1); + //let associated_data = Aad::empty(); // supplying the wrong data causes the decryption to fail + let associated_data = Aad::from(b"additional public data"); + + // Create a new AEAD key for decrypting and verifying the authentication tag + let mut opening_key = OpeningKey::new(unbound_key, nonce_sequence); + + // Decrypt the data by passing in the associated data and the cypher text with the authentication tag appended + let mut cypher_text_with_tag = [&in_out, tag.as_ref()].concat(); + let decrypted_data = opening_key.open_in_place( associated_data, &mut cypher_text_with_tag)?; + println!("decrypted_data = {}", String::from_utf8(decrypted_data.to_vec()).unwrap()); + + assert_eq!(data, decrypted_data); + Ok(()) +}