diff --git a/Cargo.lock b/Cargo.lock index c4850cd..75ad9ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,9 +206,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ "axum-core 0.5.6", "bytes", @@ -275,11 +275,11 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef252edff26ddba56bbcdf2ee3307b8129acb86f5749b68990c168a6fcc9c76" +checksum = "be44683b41ccb9ab2d23a5230015c9c3c55be97a25e4428366de8873103f7970" dependencies = [ - "axum 0.8.8", + "axum 0.8.9", "axum-core 0.5.6", "bytes", "cookie", @@ -2765,11 +2765,11 @@ dependencies = [ [[package]] name = "nanoid" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" +checksum = "8628de41fe064cc3f0cf07f3d299ee3e73521adaff72278731d5c8cae3797873" dependencies = [ - "rand 0.8.5", + "rand 0.9.2", ] [[package]] @@ -4257,7 +4257,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" name = "supernova" version = "0.1.0" dependencies = [ - "axum 0.8.8", + "axum 0.8.9", "axum-extra", "base64 0.22.1", "bitwarden", @@ -4281,6 +4281,16 @@ dependencies = [ "web-shove", ] +[[package]] +name = "supernovi" +version = "0.1.0" +dependencies = [ + "axum 0.8.9", + "bitwarden", + "dotenvy", + "tokio", +] + [[package]] name = "syn" version = "1.0.109" @@ -4456,9 +4466,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.50.0" +version = "1.52.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" dependencies = [ "bytes", "libc", @@ -4483,9 +4493,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", @@ -4887,9 +4897,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.23.0" +version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" dependencies = [ "getrandom 0.4.2", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index 60e302c..e7160d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "2" -members = ["supernova", "web-shove"] +members = ["supernova", "supernovi", "web-shove"] diff --git a/supernova/Cargo.toml b/supernova/Cargo.toml index 55e96c0..dd1f3da 100644 --- a/supernova/Cargo.toml +++ b/supernova/Cargo.toml @@ -4,25 +4,25 @@ version = "0.1.0" edition = "2024" [dependencies] -axum = { version = "0.8.8", features = [] } -axum-extra = { version = "0.12.5", features = ["cookie-private"] } +axum = { version = "0.8.9", features = [] } +axum-extra = { version = "0.12.6", features = ["cookie-private"] } base64 = "0.22.1" -bitwarden = "2.0.0" +bitwarden = { version = "2.0.0", features = ["secrets"] } cookie = "0.18.1" dotenvy = "0.15.7" getrandom = "0.4.2" libsql = "0.9.30" mime = "0.3.17" -nanoid = "0.4.0" +nanoid = "0.5.0" postcard = { version = "1.1.0", features = ["alloc"], default-features = false } reqwest = "0.13.2" serde = { version = "1.0.215", features = ["derive"] } thiserror = "2.0.3" time = { version = "0.3.36", features = ["serde"] } -tokio = { version = "1.41.1", features = ["full"] } +tokio = { version = "1.52.1", features = ["full"] } tower-http = { version = "0.6.2", features = ["fs"] } tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } url = { version = "2.5.4", features = ["serde"] } -uuid = "1.11.0" +uuid = "1.23.1" web-shove = { path = "../web-shove" } diff --git a/supernova/src/main.rs b/supernova/src/main.rs index a4d85bb..3355332 100644 --- a/supernova/src/main.rs +++ b/supernova/src/main.rs @@ -14,7 +14,6 @@ use axum::Router; use axum::routing::{get, post}; use base64::Engine; use base64::prelude::BASE64_URL_SAFE_NO_PAD; -use dotenvy::dotenv; use notification::Subscription; use secrets::Secrets; use tokio::sync::Mutex; @@ -44,7 +43,8 @@ async fn main() { .with(tracing_subscriber::fmt::layer()) .init(); - dotenv().ok(); + #[cfg(debug_assertions)] + dotenvy::dotenv().ok(); let public_path = if cfg!(debug_assertions) { Path::new(env!("CARGO_MANIFEST_DIR")).join("public") diff --git a/supernovi/Cargo.toml b/supernovi/Cargo.toml new file mode 100644 index 0000000..8aef193 --- /dev/null +++ b/supernovi/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "supernovi" +version = "0.1.0" +edition = "2024" + +[dependencies] +axum = "0.8.9" +bitwarden = { version = "2.0.0", features = ["secrets"] } +dotenvy = "0.15.7" +tokio = { version = "1.52.1", features = ["full"] } diff --git a/supernovi/src/main.rs b/supernovi/src/main.rs new file mode 100644 index 0000000..c48a83e --- /dev/null +++ b/supernovi/src/main.rs @@ -0,0 +1,21 @@ +use std::{env, error::Error}; + +use bitwarden::{Client, auth::login::AccessTokenLoginRequest}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + #[cfg(debug_assertions)] + dotenvy::dotenv().ok(); + + let client = Client::new(None); + let token = env::var("BWS_TOKEN").unwrap(); + let request = AccessTokenLoginRequest { + access_token: token, + state_file: None, + }; + let response = client.auth().login_access_token(&request).await?; + + println!("Hello, world! {:?}", response); + + Ok(()) +} diff --git a/web-shove/src/encrypted_content_encoding.rs b/web-shove/src/encrypted_content_encoding.rs deleted file mode 100644 index 29c1d5b..0000000 --- a/web-shove/src/encrypted_content_encoding.rs +++ /dev/null @@ -1,176 +0,0 @@ -use aes_gcm::{aead::AeadMutInPlace, aes::cipher::InvalidLength, KeyInit}; - -use crate::{LAST_PADDING_DELIMITER, PADDING_DELIMITER}; - -const SALT_LENGTH: usize = 16; - -// struct Test([u8; SIZE]); -// struct Header { -// salt: [u8; SALT_LENGTH], -// record_size: u32, -// key_id: [u8; KEY_ID_SIZE], -// test: Test<{ 3 + KEY_ID_SIZE }>, -// } - -// struct Content { -// content: [u8; RECORD_SIZE], -// } -struct EncryptionKey([u8; 16]); - -struct Nonce([u8; 12]); -trait CryptographyProvider { - type Error; - fn aes_128_gcm_encrypt( - &self, - plain_text: &mut [u8], - key: &EncryptionKey, - nonce: &Nonce, - ) -> Result<(), Self::Error>; -} - -struct RustCryptoProvider; -enum RustCryptoProviderError { - BadPlainTextLength, - InvalidKeyLength(InvalidLength), - InsufficientCapacity(aes_gcm::Error), -} - -impl CryptographyProvider for RustCryptoProvider { - type Error = RustCryptoProviderError; - - fn aes_128_gcm_encrypt( - &self, - original_plain_text: &mut [u8], - EncryptionKey(key): &EncryptionKey, - Nonce(nonce): &Nonce, - ) -> Result<(), Self::Error> { - //TODO this is not ergonomic - let mut plain_text = aes_gcm::aead::heapless::Vec::::new(); - - for byte in &original_plain_text[..original_plain_text.len() - 16] { - plain_text - .push(*byte) - .map_err(|_| RustCryptoProviderError::BadPlainTextLength)?; - } - - let mut cipher = aes_gcm::Aes128Gcm::new_from_slice(key) - .map_err(RustCryptoProviderError::InvalidKeyLength)?; - - let nonce = aes_gcm::Nonce::from_slice(nonce); - cipher - .encrypt_in_place(nonce, Default::default(), &mut plain_text) - .map_err(RustCryptoProviderError::InsufficientCapacity)?; - - //TODO this will panic for usecases outside of demo - original_plain_text.copy_from_slice(plain_text.as_slice()); - - Ok(()) - } -} -struct CipherText { - content: [u8; 4096], - length: usize, -} - -struct Record { - content: [u8; 4096], - length: usize, -} - -impl Record { - const PADDING_LENGTH: usize = 17; - const PADDING_DELIMITER: u8 = 0x01; - const LAST_PADDING_DELIMITER: u8 = 0x02; - - fn new() -> Self { - Self { - content: [0; 4096], - length: 0, - } - } - - #[inline] - fn capacity(&self) -> usize { - self.content.len() - } - - fn extend_from_slice(&mut self, other: &[u8]) -> Result<(), ()> { - if self.length + other.len() + Self::PADDING_LENGTH > self.capacity() { - return Err(()); - } - - for byte in other { - self.content[self.length] = *byte; - self.length += 1; - } - - Ok(()) - } - - fn encrypt( - mut self, - provider: &impl CryptographyProvider, - is_last: bool, - key: &EncryptionKey, - nonce: &Nonce, - ) -> Result { - self.content[self.length] = if is_last { - LAST_PADDING_DELIMITER - } else { - PADDING_DELIMITER - }; - - let new_length = self.length + Self::PADDING_LENGTH; - let mut buffer = &mut self.content[..new_length]; - - provider.aes_128_gcm_encrypt(buffer, key, nonce); - - Ok(CipherText { - content: self.content, - length: new_length, - }) - } -} - -#[cfg(test)] -mod test { - use base64::{prelude::BASE64_URL_SAFE_NO_PAD, Engine}; - use ring::aead::NONCE_LEN; - - use super::*; - #[test] - fn can_run_rfc_8188_example() { - // Arrange - const PLAIN_TEXT: &[u8] = b"I am the walrus"; - const EXPECETD_CONTENT: &str = - "I1BsxtFttlv3u_Oo94xnmwAAEAAA-NAVub2qFgBEuQKRapoZu-IxkIva3MEB1PD-ly8Thjg"; - - let pseudo_random_key = EncryptionKey( - BASE64_URL_SAFE_NO_PAD - .decode("_wniytB-ofscZDh4tbSjHw") - .unwrap() - .try_into() - .unwrap(), - ); - let nonce = Nonce( - BASE64_URL_SAFE_NO_PAD - .decode("Bcs8gkIRKLI8GeI8") - .unwrap() - .try_into() - .unwrap(), - ); - - let provider = RustCryptoProvider; - // Act - let mut content = Record::new(); - content.extend_from_slice(PLAIN_TEXT).unwrap(); - - let encrypted = content - .encrypt(&provider, true, &pseudo_random_key, &nonce) - .unwrap(); - let actual = BASE64_URL_SAFE_NO_PAD.encode(&encrypted.content); - - // Assert - assert_eq!(EXPECETD_CONTENT, actual); - } -} diff --git a/web-shove/src/experiments.rs b/web-shove/src/experiments.rs deleted file mode 100644 index ca61040..0000000 --- a/web-shove/src/experiments.rs +++ /dev/null @@ -1,13 +0,0 @@ -/// Restrict key id to length of <=255 as defined by the specification but do it at compile time -struct KeyId([u8; LENGTH]); -impl KeyId { - pub fn new(key_id: [u8; LENGTH]) -> Self { - const { - assert!( - LENGTH <= u8::MAX as usize, - "Key id length is greater than 255" - ) - }; - Self(key_id) - } -} diff --git a/web-shove/src/lib.rs b/web-shove/src/lib.rs index d147c3a..1d708bd 100644 --- a/web-shove/src/lib.rs +++ b/web-shove/src/lib.rs @@ -4,8 +4,6 @@ use ::rand::{RngCore, SeedableRng}; use aes_gcm::{KeyInit, aead::AeadMutInPlace}; use libcrux_hkdf::{Hkdf, Sha2_256}; pub mod authorization_header; -mod encrypted_content_encoding; -mod experiments; pub mod vapid; const KEY_INFO: &[u8; 13] = b"WebPush: info";