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 KeyDerivation for HKDFParams {
35 const INDEX: usize = KeyDerivationMethod::HKDF as usize;
36
37 fn lock(
38 &mut self,
39 content_key: &SymmetricKey,
40 secret: impl AsRef<[u8]>,
41 ) -> Result<EncryptedMessage> {
42 let derived_key: SymmetricKey = (match self.hash_type {
43 HashType::SHA256 => hkdf_hmac_sha256(secret, &self.salt, 32),
44 HashType::SHA512 => hkdf_hmac_sha512(secret, &self.salt, 32),
45 })
46 .try_into()
47 .unwrap();
48 let encoded_method: Vec<u8> = self.to_cbor_data();
49 Ok(derived_key.encrypt(
50 content_key,
51 Some(encoded_method),
52 Option::<Nonce>::None,
53 ))
54 }
55
56 fn unlock(
57 &self,
58 encrypted_message: &EncryptedMessage,
59 secret: impl AsRef<[u8]>,
60 ) -> Result<SymmetricKey> {
61 let derived_key: SymmetricKey = (match self.hash_type {
62 HashType::SHA256 => hkdf_hmac_sha256(secret, &self.salt, 32),
63 HashType::SHA512 => hkdf_hmac_sha512(secret, &self.salt, 32),
64 })
65 .try_into()?;
66 let content_key = derived_key.decrypt(encrypted_message)?.try_into()?;
67 Ok(content_key)
68 }
69}
70
71impl std::fmt::Display for HKDFParams {
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 write!(f, "HKDF({})", self.hash_type)
74 }
75}
76
77impl Into<CBOR> for HKDFParams {
78 fn into(self) -> CBOR {
79 vec![
80 CBOR::from(Self::INDEX),
81 self.salt.into(),
82 self.hash_type.into(),
83 ]
84 .into()
85 }
86}
87
88impl TryFrom<CBOR> for HKDFParams {
89 type Error = dcbor::Error;
90
91 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
92 let a = cbor.try_into_array()?;
93 a.len()
94 .eq(&3)
95 .then_some(())
96 .ok_or_else(|| dcbor::Error::msg("Invalid HKDFParams"))?;
97 let mut iter = a.into_iter();
98 let _index: usize = iter
99 .next()
100 .ok_or_else(|| dcbor::Error::msg("Missing index"))?
101 .try_into()?;
102 let salt: Salt = iter
103 .next()
104 .ok_or_else(|| dcbor::Error::msg("Missing salt"))?
105 .try_into()?;
106 let hash_type: HashType = iter
107 .next()
108 .ok_or_else(|| dcbor::Error::msg("Missing hash type"))?
109 .try_into()?;
110 Ok(Self { salt, hash_type })
111 }
112}