From 04142dc116a243ffee7ce56465739b635d30f611 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sun, 3 May 2026 20:51:29 -0400 Subject: [PATCH] feat(core): add derive_master_key_raw + RecoveryQr error variant --- crates/relicario-core/src/crypto.rs | 17 +++++++++++++++++ crates/relicario-core/src/error.rs | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/crates/relicario-core/src/crypto.rs b/crates/relicario-core/src/crypto.rs index d28b0bb..78426b4 100644 --- a/crates/relicario-core/src/crypto.rs +++ b/crates/relicario-core/src/crypto.rs @@ -243,6 +243,23 @@ pub fn derive_master_key( Ok(output) } +/// Like `derive_master_key` but takes an already-assembled `input` byte slice directly, +/// allowing callers to apply their own domain separation before KDF. +pub fn derive_master_key_raw( + input: &[u8], + salt: &[u8; 32], + params: &KdfParams, +) -> Result> { + let argon2_params = Params::new(params.argon2_m, params.argon2_t, params.argon2_p, Some(32)) + .map_err(|e| RelicarioError::Kdf(e.to_string()))?; + let argon2 = Argon2::new(Algorithm::Argon2id, Version::V0x13, argon2_params); + let mut output = Zeroizing::new([0u8; 32]); + argon2 + .hash_password_into(input, salt, output.as_mut()) + .map_err(|e| RelicarioError::Kdf(e.to_string()))?; + Ok(output) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/relicario-core/src/error.rs b/crates/relicario-core/src/error.rs index 5b3d131..076d1f3 100644 --- a/crates/relicario-core/src/error.rs +++ b/crates/relicario-core/src/error.rs @@ -119,6 +119,10 @@ pub enum RelicarioError { /// immediately. Use TOTP instead. #[error("HOTP is not supported: counter persistence requires vault save after each use")] HotpNotSupported, + + /// Recovery QR generation or parsing failed. + #[error("recovery QR: {0}")] + RecoveryQr(String), } /// Crate-wide result alias, reducing boilerplate in function signatures.