bc_components/encrypted_key/
key_derivation_params.rs

1use anyhow::Result;
2use dcbor::prelude::*;
3
4use super::{
5    Argon2idParams, HKDFParams, KeyDerivation, KeyDerivationMethod,
6    PBKDF2Params, SSHAgentParams, ScryptParams,
7};
8use crate::{EncryptedMessage, SymmetricKey};
9
10/// Enum representing the derivation parameters.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum KeyDerivationParams {
13    HKDF(HKDFParams),
14    PBKDF2(PBKDF2Params),
15    Scrypt(ScryptParams),
16    Argon2id(Argon2idParams),
17    SSHAgent(SSHAgentParams),
18}
19
20impl KeyDerivationParams {
21    /// Returns the key derivation method associated with the parameters.
22    pub fn method(&self) -> KeyDerivationMethod {
23        match self {
24            KeyDerivationParams::HKDF(_) => KeyDerivationMethod::HKDF,
25            KeyDerivationParams::PBKDF2(_) => KeyDerivationMethod::PBKDF2,
26            KeyDerivationParams::Scrypt(_) => KeyDerivationMethod::Scrypt,
27            KeyDerivationParams::Argon2id(_) => KeyDerivationMethod::Argon2id,
28            KeyDerivationParams::SSHAgent(_) => KeyDerivationMethod::SSHAgent,
29        }
30    }
31
32    pub fn is_password_based(&self) -> bool {
33        matches!(
34            self,
35            KeyDerivationParams::PBKDF2(_)
36                | KeyDerivationParams::Scrypt(_)
37                | KeyDerivationParams::Argon2id(_)
38        )
39    }
40
41    pub fn is_ssh_agent(&self) -> bool {
42        matches!(self, KeyDerivationParams::SSHAgent(_))
43    }
44
45    pub fn lock(
46        &mut self,
47        content_key: &SymmetricKey,
48        secret: impl AsRef<[u8]>,
49    ) -> Result<EncryptedMessage> {
50        match self {
51            KeyDerivationParams::HKDF(params) => {
52                params.lock(content_key, secret)
53            }
54            KeyDerivationParams::PBKDF2(params) => {
55                params.lock(content_key, secret)
56            }
57            KeyDerivationParams::Scrypt(params) => {
58                params.lock(content_key, secret)
59            }
60            KeyDerivationParams::Argon2id(params) => {
61                params.lock(content_key, secret)
62            }
63            KeyDerivationParams::SSHAgent(params) => {
64                params.lock(content_key, secret)
65            }
66        }
67    }
68}
69
70impl std::fmt::Display for KeyDerivationParams {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        match self {
73            KeyDerivationParams::HKDF(params) => write!(f, "{}", params),
74            KeyDerivationParams::PBKDF2(params) => write!(f, "{}", params),
75            KeyDerivationParams::Scrypt(params) => write!(f, "{}", params),
76            KeyDerivationParams::Argon2id(params) => write!(f, "{}", params),
77            KeyDerivationParams::SSHAgent(params) => write!(f, "{}", params),
78        }
79    }
80}
81
82impl From<KeyDerivationParams> for CBOR {
83    fn from(value: KeyDerivationParams) -> Self {
84        match value {
85            KeyDerivationParams::HKDF(params) => params.into(),
86            KeyDerivationParams::PBKDF2(params) => params.into(),
87            KeyDerivationParams::Scrypt(params) => params.into(),
88            KeyDerivationParams::Argon2id(params) => params.into(),
89            KeyDerivationParams::SSHAgent(params) => params.into(),
90        }
91    }
92}
93
94impl TryFrom<CBOR> for KeyDerivationParams {
95    type Error = dcbor::Error;
96
97    fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
98        let a = cbor.clone().try_into_array()?;
99        let mut iter = a.into_iter();
100        let index: usize = iter
101            .next()
102            .ok_or_else(|| dcbor::Error::msg("Missing index"))?
103            .try_into()?;
104        match KeyDerivationMethod::from_index(index) {
105            Some(KeyDerivationMethod::HKDF) => {
106                Ok(KeyDerivationParams::HKDF(HKDFParams::try_from(cbor)?))
107            }
108            Some(KeyDerivationMethod::PBKDF2) => {
109                Ok(KeyDerivationParams::PBKDF2(PBKDF2Params::try_from(cbor)?))
110            }
111            Some(KeyDerivationMethod::Scrypt) => {
112                Ok(KeyDerivationParams::Scrypt(ScryptParams::try_from(cbor)?))
113            }
114            Some(KeyDerivationMethod::Argon2id) => Ok(
115                KeyDerivationParams::Argon2id(Argon2idParams::try_from(cbor)?),
116            ),
117            Some(KeyDerivationMethod::SSHAgent) => Ok(
118                KeyDerivationParams::SSHAgent(SSHAgentParams::try_from(cbor)?),
119            ),
120            None => Err(dcbor::Error::msg("Invalid KeyDerivationMethod")),
121        }
122    }
123}