From 86e2d776718ab7e75996c12be503a2af2542d913 Mon Sep 17 00:00:00 2001 From: vdang Date: Tue, 20 Jun 2023 10:38:41 +0200 Subject: [PATCH] Add a builder function that uses argon2 by default --- plugins/stronghold/src/kdf.rs | 20 +++++++++++++++++++- plugins/stronghold/src/lib.rs | 32 ++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/plugins/stronghold/src/kdf.rs b/plugins/stronghold/src/kdf.rs index 5c9483b0..fc76c31a 100644 --- a/plugins/stronghold/src/kdf.rs +++ b/plugins/stronghold/src/kdf.rs @@ -2,14 +2,19 @@ use argon2::Argon2; use rand_chacha::ChaCha20Rng; use rand_core::{RngCore, SeedableRng}; use std::path::PathBuf; +use tauri::Config; /// NOTE: Hash supplied to Stronghold must be 32bits long. /// This is a current limitation of Stronghold. const HASH_LENGTH: usize = 32; +const SALT_FILENAME: &str = "stronghold_salt.txt"; pub struct KeyDerivation {} impl KeyDerivation { + /// Will create a key from [`password`] and a generated salt. + /// Salt will be generated to file [`salt_path`] or taken from it + /// if file already exists pub fn argon2(password: &str, salt_path: &PathBuf) -> Vec { let mut salt = [0u8; HASH_LENGTH]; create_or_get_salt(&mut salt, salt_path); @@ -20,10 +25,23 @@ impl KeyDerivation { .expect("Failed to generate hash for password"); encoded.to_vec() } + + /// Will create a key from [`password`] and a generated salt. + /// Salt will be generated/taken from a default file in the Tauri local + /// directory + pub fn argon2_with_config(password: &str, tauri_config: &Config) -> Vec { + let salt_dir = tauri::api::path::app_local_data_dir(tauri_config) + .expect("Application local directory not found"); + let mut salt_path = PathBuf::new(); + salt_path.push(salt_dir); + salt_path.push(SALT_FILENAME); + + KeyDerivation::argon2(password, &salt_path) + } } // NOTE: this is not ideal as we produce a single salt per application -// rather than having different salt for each Stronghold snapshot +// rather than having different salt for each Stronghold snapshot/password fn create_or_get_salt(salt: &mut [u8], salt_path: &PathBuf) { if salt_path.is_file() { // Get existing salt diff --git a/plugins/stronghold/src/lib.rs b/plugins/stronghold/src/lib.rs index 6beb8b15..0695d73d 100644 --- a/plugins/stronghold/src/lib.rs +++ b/plugins/stronghold/src/lib.rs @@ -408,15 +408,35 @@ impl Builder { } } + /// Initializes a stronghold plugin with argon2 as a default kdf + pub fn init_and_build_with_argon2() -> TauriPlugin { + let plugin_builder = PluginBuilder::new("stronghold").setup(move |app| { + let app2 = app.clone(); + app.manage(StrongholdCollection::default()); + app.manage(PasswordHashFunction(Box::new(move |pwd: &str| { + kdf::KeyDerivation::argon2_with_config(pwd, &app2.config()) + }))); + Ok(()) + }); + Builder::invoke_stronghold_handlers_and_build(plugin_builder) + } + pub fn build(self) -> TauriPlugin { let password_hash_function = self.password_hash_function; - PluginBuilder::new("stronghold") - .setup(move |app| { - app.manage(StrongholdCollection::default()); - app.manage(PasswordHashFunction(password_hash_function)); - Ok(()) - }) + let plugin_builder = PluginBuilder::new("stronghold").setup(move |app| { + app.manage(StrongholdCollection::default()); + app.manage(PasswordHashFunction(password_hash_function)); + Ok(()) + }); + + Builder::invoke_stronghold_handlers_and_build(plugin_builder) + } + + fn invoke_stronghold_handlers_and_build( + builder: PluginBuilder, + ) -> TauriPlugin { + builder .invoke_handler(tauri::generate_handler![ initialize, destroy,