bc_components/encrypted_key/
hkdf_params.rs

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