bc_components/encrypted_key/
scrypt_params.rs

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