bc_components/encrypted_key/
scrypt_params.rs

1use 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/// Struct representing Scrypt parameters.
9///
10/// CDDL:
11/// ```cddl
12/// ScryptParams = [2, Salt, log_n: uint, r: uint, p: uint]
13/// ```
14#[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 Default for ScryptParams {
41    fn default() -> Self { Self::new() }
42}
43
44impl KeyDerivation for ScryptParams {
45    const INDEX: usize = KeyDerivationMethod::Scrypt as usize;
46    fn lock(
47        &mut self,
48        content_key: &SymmetricKey,
49        secret: impl AsRef<[u8]>,
50    ) -> Result<EncryptedMessage> {
51        let derived_key: SymmetricKey =
52            scrypt_opt(secret, &self.salt, 32, self.log_n, self.r, self.p)
53                .try_into()
54                .unwrap();
55        let encoded_method: Vec<u8> = self.to_cbor_data();
56        Ok(derived_key.encrypt(
57            content_key,
58            Some(encoded_method),
59            Option::<Nonce>::None,
60        ))
61    }
62
63    fn unlock(
64        &self,
65        encrypted_message: &EncryptedMessage,
66        secret: impl AsRef<[u8]>,
67    ) -> Result<SymmetricKey> {
68        let derived_key: SymmetricKey =
69            scrypt_opt(secret, &self.salt, 32, self.log_n, self.r, self.p)
70                .try_into()?;
71        derived_key.decrypt(encrypted_message)?.try_into()
72    }
73}
74
75impl std::fmt::Display for ScryptParams {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        write!(f, "Scrypt")
78    }
79}
80
81impl From<ScryptParams> for CBOR {
82    fn from(val: ScryptParams) -> Self {
83        vec![
84            CBOR::from(ScryptParams::INDEX),
85            val.salt.into(),
86            val.log_n.into(),
87            val.r.into(),
88            val.p.into(),
89        ]
90        .into()
91    }
92}
93
94impl TryFrom<CBOR> for ScryptParams {
95    type Error = dcbor::Error;
96
97    fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
98        let a = cbor.try_into_array()?;
99        a.len()
100            .eq(&5)
101            .then_some(())
102            .ok_or_else(|| dcbor::Error::msg("Invalid ScryptParams"))?;
103        let mut iter = a.into_iter();
104        let _index: usize = iter
105            .next()
106            .ok_or_else(|| dcbor::Error::msg("Missing index"))?
107            .try_into()?;
108        let salt: Salt = iter
109            .next()
110            .ok_or_else(|| dcbor::Error::msg("Missing salt"))?
111            .try_into()?;
112        let log_n: u8 = iter
113            .next()
114            .ok_or_else(|| dcbor::Error::msg("Missing log_n"))?
115            .try_into()?;
116        let r: u32 = iter
117            .next()
118            .ok_or_else(|| dcbor::Error::msg("Missing r"))?
119            .try_into()?;
120        let p: u32 = iter
121            .next()
122            .ok_or_else(|| dcbor::Error::msg("Missing p"))?
123            .try_into()?;
124        Ok(Self { salt, log_n, r, p })
125    }
126}