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