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