bc_components/encrypted_key/
key_derivation_params.rs

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