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 Default for Argon2idParams {
30    fn default() -> Self { Self::new() }
31}
32
33impl KeyDerivation for Argon2idParams {
34    const INDEX: usize = KeyDerivationMethod::Argon2id as usize;
35
36    fn lock(
37        &mut self,
38        content_key: &SymmetricKey,
39        secret: impl AsRef<[u8]>,
40    ) -> Result<EncryptedMessage> {
41        let derived_key: SymmetricKey =
42            argon2id(secret, &self.salt, 32).try_into().unwrap();
43        let encoded_method: Vec<u8> = self.to_cbor_data();
44        Ok(derived_key.encrypt(
45            content_key,
46            Some(encoded_method),
47            Option::<Nonce>::None,
48        ))
49    }
50
51    fn unlock(
52        &self,
53        encrypted_message: &EncryptedMessage,
54        secret: impl AsRef<[u8]>,
55    ) -> Result<SymmetricKey> {
56        let derived_key: SymmetricKey =
57            argon2id(secret, &self.salt, 32).try_into()?;
58        derived_key.decrypt(encrypted_message)?.try_into()
59    }
60}
61
62impl std::fmt::Display for Argon2idParams {
63    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
64        write!(f, "Argon2id")
65    }
66}
67
68impl From<Argon2idParams> for CBOR {
69    fn from(val: Argon2idParams) -> Self {
70        vec![CBOR::from(Argon2idParams::INDEX), val.salt.into()].into()
71    }
72}
73
74impl TryFrom<CBOR> for Argon2idParams {
75    type Error = dcbor::Error;
76
77    fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
78        let a = cbor.try_into_array()?;
79        a.len()
80            .eq(&2)
81            .then_some(())
82            .ok_or_else(|| dcbor::Error::msg("Invalid Argon2idParams"))?;
83        let mut iter = a.into_iter();
84        let _index: usize = iter
85            .next()
86            .ok_or_else(|| dcbor::Error::msg("Missing index"))?
87            .try_into()?;
88        let salt: Salt = iter
89            .next()
90            .ok_or_else(|| dcbor::Error::msg("Missing salt"))?
91            .try_into()?;
92        Ok(Argon2idParams { salt })
93    }
94}