From 1bb97f00b57bf111b9de842ba3bf1846183689a1 Mon Sep 17 00:00:00 2001 From: vdang Date: Mon, 19 Jun 2023 18:30:54 +0200 Subject: [PATCH] Add accessible argon2 kdf --- Cargo.lock | 25 +++++++++++++++++++++++ plugins/stronghold/Cargo.toml | 11 +++++++++- plugins/stronghold/src/kdf.rs | 38 +++++++++++++++++++++++++++++++++++ plugins/stronghold/src/lib.rs | 3 +++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 plugins/stronghold/src/kdf.rs diff --git a/Cargo.lock b/Cargo.lock index 500fcca3..6a2c8a48 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,6 +102,17 @@ version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +[[package]] +name = "argon2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95c2fcf79ad1932ac6269a738109997a83c227c09b75842ae564dc8ede6a861c" +dependencies = [ + "base64ct", + "blake2", + "password-hash", +] + [[package]] name = "arrayref" version = "0.3.6" @@ -2850,6 +2861,17 @@ dependencies = [ "windows-sys 0.42.0", ] +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "paste" version = "1.0.11" @@ -4458,11 +4480,14 @@ dependencies = [ name = "tauri-plugin-stronghold" version = "0.0.0" dependencies = [ + "argon2", "hex", "iota-crypto 0.21.0", "iota_stronghold", "log", "rand 0.8.5", + "rand_chacha 0.3.1", + "rand_core 0.6.4", "rusty-fork", "serde", "serde_json", diff --git a/plugins/stronghold/Cargo.toml b/plugins/stronghold/Cargo.toml index 57a8a2c9..1c2d769a 100644 --- a/plugins/stronghold/Cargo.toml +++ b/plugins/stronghold/Cargo.toml @@ -20,6 +20,15 @@ iota-crypto = "0.21" hex = "0.4" zeroize = { version = "1", features = ["zeroize_derive"] } +# kdf dependincies +argon2 = { version = "0.5.0", optional = true } +rand_chacha = { version = "0.3.1", optional = true } +rand_core = { version = "0.6.4", features = ["getrandom"], optional = true } + [dev-dependencies] rand = "0.8" -rusty-fork = "0.3" \ No newline at end of file +rusty-fork = "0.3" + +[features] +default = ["kdf"] +kdf = ["dep:argon2", "dep:rand_chacha", "dep:rand_core"] diff --git a/plugins/stronghold/src/kdf.rs b/plugins/stronghold/src/kdf.rs new file mode 100644 index 00000000..5c9483b0 --- /dev/null +++ b/plugins/stronghold/src/kdf.rs @@ -0,0 +1,38 @@ +use argon2::Argon2; +use rand_chacha::ChaCha20Rng; +use rand_core::{RngCore, SeedableRng}; +use std::path::PathBuf; + +/// NOTE: Hash supplied to Stronghold must be 32bits long. +/// This is a current limitation of Stronghold. +const HASH_LENGTH: usize = 32; + +pub struct KeyDerivation {} + +impl KeyDerivation { + pub fn argon2(password: &str, salt_path: &PathBuf) -> Vec { + let mut salt = [0u8; HASH_LENGTH]; + create_or_get_salt(&mut salt, salt_path); + + let mut encoded = [0u8; HASH_LENGTH]; + Argon2::default() + .hash_password_into(password.as_bytes(), &salt, &mut encoded) + .expect("Failed to generate hash for password"); + encoded.to_vec() + } +} + +// NOTE: this is not ideal as we produce a single salt per application +// rather than having different salt for each Stronghold snapshot +fn create_or_get_salt(salt: &mut [u8], salt_path: &PathBuf) { + if salt_path.is_file() { + // Get existing salt + let tmp = std::fs::read(&salt_path).unwrap(); + salt.clone_from_slice(&tmp); + } else { + // Generate new salt + let mut gen = ChaCha20Rng::from_entropy(); + gen.fill_bytes(salt); + std::fs::write(salt_path, salt).expect("Failed to write salt for Stronghold") + } +} diff --git a/plugins/stronghold/src/lib.rs b/plugins/stronghold/src/lib.rs index b14b6990..6beb8b15 100644 --- a/plugins/stronghold/src/lib.rs +++ b/plugins/stronghold/src/lib.rs @@ -22,6 +22,9 @@ use tauri::{ }; use zeroize::Zeroize; +#[cfg(feature = "kdf")] +pub mod kdf; + pub mod stronghold; type PasswordHashFn = dyn Fn(&str) -> Vec + Send + Sync;