bc_components/encrypted_key/
argon2id_params.rs1use anyhow::Result;
2use bc_crypto::argon2id;
3use dcbor::prelude::*;
4
5use super::{KeyDerivation, KeyDerivationMethod, SALT_LEN};
6use crate::{EncryptedMessage, Nonce, Salt, SymmetricKey};
7
8#[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}