bc_components/encrypted_key/
hkdf_params.rs

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