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