bc_components/encrypted_key/
key_derivation_params.rs

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