bc_components/encrypted_key/
hkdf_params.rs1use 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#[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}