From ed34a5251f13bbded0aa15719887db4924b351eb Mon Sep 17 00:00:00 2001 From: benj Date: Mon, 22 May 2023 15:47:06 -0700 Subject: update credential API to include sessions This change updates the credential API to include sessions as just another credential type. It adds the ApiToken type and enables revocation of credentials. Updates were also made to the Identity API which now includes a list of new credentials added to an Identity. This change also migrates off the hacky ENV configuration paradigm and includes a new config.toml file specified by the SECD_CONFIG_PATH env var. No default is currently provided. Clippy updates and code cleanup. --- crates/secd/src/util/crypter.rs | 47 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 15 deletions(-) (limited to 'crates/secd/src/util/crypter.rs') diff --git a/crates/secd/src/util/crypter.rs b/crates/secd/src/util/crypter.rs index 1717377..e5ec796 100644 --- a/crates/secd/src/util/crypter.rs +++ b/crates/secd/src/util/crypter.rs @@ -3,8 +3,8 @@ use aes_gcm::{ Aes256Gcm, Nonce, }; use argon2::{ - password_hash::{self, SaltString}, - Argon2, PasswordHasher, + password_hash::{Salt, SaltString}, + Argon2, PasswordHash, PasswordHasher, }; use derive_more::Display; use rand::Rng; @@ -13,10 +13,10 @@ use thiserror::Error; #[derive(Debug, Display, Error)] pub enum CrypterError { - EncryptError(String), - DecryptError(String), - DecodeError(String), - HashError(String), + Encrypt(String), + Decrypt(String), + Decode(String), + Hash(String), } pub struct Crypter { @@ -37,8 +37,8 @@ impl Crypter { let rbs = rand::thread_rng().gen::<[u8; 12]>(); let iv = Nonce::from_slice(&rbs); let crypt = cipher - .encrypt(&iv, data) - .map_err(|e| CrypterError::EncryptError(e.to_string()))?; + .encrypt(iv, data) + .map_err(|e| CrypterError::Encrypt(e.to_string()))?; let mut msg = iv.to_vec(); msg.extend_from_slice(&crypt); @@ -53,19 +53,36 @@ impl Crypter { let iv = Nonce::from_slice(&data[0..=11]); let data = &data[12..]; - Ok(cipher - .decrypt(&iv, data) - .map_err(|e| CrypterError::DecryptError(e.to_string()))?) + cipher + .decrypt(iv, data) + .map_err(|e| CrypterError::Decrypt(e.to_string())) } - pub fn hash(&self, data: &[u8]) -> Result { - let salt = SaltString::generate(&mut OsRng); + /// Hash data. + /// If a candidate is provided, then use that candidate's salt, passed as a full phc string. + pub fn hash(&self, data: &[u8], phc_candidate: Option<&str>) -> Result { + let salt = match phc_candidate { + None => SaltString::generate(&mut OsRng).as_str().to_owned(), + Some(phc) => PasswordHash::new(phc) + .map_err(|e| CrypterError::Hash(e.to_string()))? + .salt.expect("unreachable fbacabb8-082a-423a-abff-06a961dc5828 [no salt found means a forced error since all resources, even those of high entropy, are salted]").as_str().to_owned(), + }; + let hasher = Argon2::default(); Ok(hasher - .hash_password(data, &salt) - .map_err(|e| CrypterError::HashError(e.to_string()))? + .hash_password( + data, + Salt::from_b64(&salt).map_err(|e| CrypterError::Hash(e.to_string()))?, + ) + .map_err(|e| CrypterError::Hash(e.to_string()))? .to_string()) } + + pub fn weak_hash(&self, data: &[u8]) -> Result { + let mut hasher = Sha256::new(); + hasher.update(data); + Ok(hex::encode(hasher.finalize())) + } } #[cfg(test)] -- cgit v1.2.3