Skip to main content

devolutions_crypto/key_derivation/
key_derivation_v2.rs

1//! Key Derivation V2: Argon2id
2use std::convert::TryFrom;
3
4use zeroize::Zeroizing;
5
6use crate::key::{secret_key_from_raw, SecretKey};
7use crate::{Argon2Parameters, Error, Header, KeyDerivationVersion, Result};
8
9use super::{DerivationParameters, DerivationParametersPayload};
10
11#[derive(Clone)]
12pub struct KeyDerivationV2 {
13    pub params: Argon2Parameters,
14}
15
16impl core::fmt::Debug for KeyDerivationV2 {
17    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
18        write!(f, "KeyDerivationV2")
19    }
20}
21
22impl KeyDerivationV2 {
23    pub fn derive(&self, key: &[u8]) -> Result<Zeroizing<Vec<u8>>> {
24        Ok(Zeroizing::new(self.params.compute(key)?))
25    }
26}
27
28impl From<&KeyDerivationV2> for Vec<u8> {
29    fn from(v2: &KeyDerivationV2) -> Self {
30        Vec::from(&v2.params)
31    }
32}
33
34impl TryFrom<&[u8]> for KeyDerivationV2 {
35    type Error = Error;
36
37    fn try_from(data: &[u8]) -> Result<Self> {
38        Ok(KeyDerivationV2 {
39            params: Argon2Parameters::try_from(data)?,
40        })
41    }
42}
43
44// ── Argon2 ───────────────────────────────────────────────────────────────────
45
46/// Derives a key using Argon2id (V2, the default).
47pub struct Argon2 {
48    params: Argon2Parameters,
49}
50
51impl Argon2 {
52    /// Creates an `Argon2` key derivation object with default parameters.
53    pub fn new() -> Self {
54        Self {
55            params: Argon2Parameters::default(),
56        }
57    }
58
59    /// Creates an `Argon2` key derivation object with custom `Argon2Parameters`.
60    /// The caller is responsible for managing the salt (use `params.set_salt()` if needed).
61    pub fn with_params(params: Argon2Parameters) -> Self {
62        Self { params }
63    }
64
65    /// Returns a `DerivationParameters` capturing the current Argon2 settings.
66    /// Useful for passing custom parameters to [`crate::password_hash::hash_password_with_parameters`].
67    pub fn parameters(self) -> DerivationParameters {
68        let v2 = KeyDerivationV2 {
69            params: self.params,
70        };
71        let mut header: Header<DerivationParameters> = Header::default();
72        header.version = KeyDerivationVersion::V2;
73        DerivationParameters {
74            header,
75            payload: DerivationParametersPayload::V2(v2),
76        }
77    }
78
79    /// Derives the key using the configured Argon2 parameters.
80    /// The salt is embedded in `Argon2Parameters` (generated at construction time when using `new()`).
81    pub fn derive(&self, key: &[u8]) -> Result<(SecretKey, DerivationParameters)> {
82        let v2 = KeyDerivationV2 {
83            params: self.params.clone(),
84        };
85        let raw = v2.derive(key)?;
86        let secret_key = secret_key_from_raw(raw)?;
87
88        let mut header: Header<DerivationParameters> = Header::default();
89        header.version = KeyDerivationVersion::V2;
90
91        let derivation_params = DerivationParameters {
92            header,
93            payload: DerivationParametersPayload::V2(v2),
94        };
95
96        Ok((secret_key, derivation_params))
97    }
98}
99
100impl Default for Argon2 {
101    fn default() -> Self {
102        Self::new()
103    }
104}