bc_components/encrypted_key/
argon2id_params.rs

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