bc_components/encrypted_key/
argon2id_params.rs

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