bc_components/encrypted_key/
pbkdf2_params.rs

1use bc_crypto::{hash::pbkdf2_hmac_sha512, pbkdf2_hmac_sha256};
2use dcbor::prelude::*;
3
4use super::{HashType, KeyDerivation, KeyDerivationMethod, SALT_LEN};
5use crate::{EncryptedMessage, Nonce, Result, Salt, SymmetricKey};
6
7/// Struct representing PBKDF2 parameters.
8///
9/// CDDL:
10/// ```cddl
11/// PBKDF2Params = [1, Salt, iterations: uint, HashType]
12/// ```
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct PBKDF2Params {
15    salt: Salt,
16    iterations: u32,
17    hash_type: HashType,
18}
19
20impl PBKDF2Params {
21    pub fn new() -> Self {
22        Self::new_opt(
23            Salt::new_with_len(SALT_LEN).unwrap(),
24            100_000,
25            HashType::SHA256,
26        )
27    }
28
29    pub fn new_opt(salt: Salt, iterations: u32, hash_type: HashType) -> Self {
30        Self { salt, iterations, hash_type }
31    }
32
33    pub fn salt(&self) -> &Salt { &self.salt }
34
35    pub fn iterations(&self) -> u32 { self.iterations }
36
37    pub fn hash_type(&self) -> HashType { self.hash_type }
38}
39
40impl Default for PBKDF2Params {
41    fn default() -> Self { Self::new() }
42}
43
44impl KeyDerivation for PBKDF2Params {
45    const INDEX: usize = KeyDerivationMethod::PBKDF2 as usize;
46
47    fn lock(
48        &mut self,
49        content_key: &SymmetricKey,
50        secret: impl AsRef<[u8]>,
51    ) -> Result<EncryptedMessage> {
52        let derived_key: SymmetricKey = (match self.hash_type {
53            HashType::SHA256 => {
54                pbkdf2_hmac_sha256(secret, &self.salt, self.iterations, 32)
55            }
56            HashType::SHA512 => {
57                pbkdf2_hmac_sha512(secret, &self.salt, self.iterations, 32)
58            }
59        })
60        .try_into()
61        .unwrap();
62        let encoded_method: Vec<u8> = self.to_cbor_data();
63        Ok(derived_key.encrypt(
64            content_key,
65            Some(encoded_method),
66            Option::<Nonce>::None,
67        ))
68    }
69
70    fn unlock(
71        &self,
72        encrypted_message: &EncryptedMessage,
73        secret: impl AsRef<[u8]>,
74    ) -> Result<SymmetricKey> {
75        let derived_key: SymmetricKey = (match self.hash_type {
76            HashType::SHA256 => {
77                pbkdf2_hmac_sha256(secret, &self.salt, self.iterations, 32)
78            }
79            HashType::SHA512 => {
80                pbkdf2_hmac_sha512(secret, &self.salt, self.iterations, 32)
81            }
82        })
83        .try_into()?;
84        derived_key.decrypt(encrypted_message)?.try_into()
85    }
86}
87
88impl std::fmt::Display for PBKDF2Params {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        write!(f, "PBKDF2({})", self.hash_type)
91    }
92}
93
94impl From<PBKDF2Params> for CBOR {
95    fn from(val: PBKDF2Params) -> Self {
96        vec![
97            CBOR::from(PBKDF2Params::INDEX),
98            val.salt.into(),
99            val.iterations.into(),
100            val.hash_type.into(),
101        ]
102        .into()
103    }
104}
105
106impl TryFrom<CBOR> for PBKDF2Params {
107    type Error = dcbor::Error;
108
109    fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
110        let a = cbor.try_into_array()?;
111        a.len()
112            .eq(&4)
113            .then_some(())
114            .ok_or_else(|| dcbor::Error::msg("Invalid PBKDF2Params"))?;
115        let mut iter = a.into_iter();
116        let _index: usize = iter
117            .next()
118            .ok_or_else(|| dcbor::Error::msg("Missing index"))?
119            .try_into()?;
120        let salt: Salt = iter
121            .next()
122            .ok_or_else(|| dcbor::Error::msg("Missing salt"))?
123            .try_into()?;
124        let iterations: u32 = iter
125            .next()
126            .ok_or_else(|| dcbor::Error::msg("Missing iterations"))?
127            .try_into()?;
128        let hash_type: HashType = iter
129            .next()
130            .ok_or_else(|| dcbor::Error::msg("Missing hash type"))?
131            .try_into()?;
132        Ok(Self { salt, iterations, hash_type })
133    }
134}