Skip to main content

sendcipher_core/crypto/
cypher_key.rs

1/* Created on 2025.10.18 */
2/* Copyright (c) 2025-2026 Youcef Lemsafer */
3/* SPDX-License-Identifier: MIT */
4
5use crate::crypto::Argon2idParams;
6use crate::crypto::random::*;
7use argon2::Argon2;
8use hmac::Mac;
9use serde::Deserialize;
10use serde::Serialize;
11
12impl From<argon2::Error> for crate::error::Error {
13    fn from(argon2_error: argon2::Error) -> Self {
14        crate::error::Error::Any(argon2_error.to_string())
15    }
16}
17
18#[derive(Clone, Serialize, Deserialize)]
19pub(crate) struct CypherKey {
20    key: Vec<u8>,
21}
22
23impl CypherKey {
24    pub fn with_key(key: Vec<u8>) -> Self {
25        Self { key: key }
26    }
27    pub fn new() -> Result<Self, crate::error::Error> {
28        Ok(Self {
29            key: crate::crypto::random::get_rand_bytes(32)?,
30        })
31    }
32
33    pub fn get_key(&self) -> &Vec<u8> {
34        &self.key
35    }
36
37    pub fn derive_key(&self, context: &[u8]) -> Vec<u8> {
38        let output_len = self.key.len();
39        hmac::Hmac::<sha2::Sha256>::new_from_slice(&self.key)
40            .expect("Expected a key valid for HMAC-SHA256")
41            .chain_update(context)
42            .finalize()
43            .into_bytes()[..output_len]
44            .to_vec()
45    }
46
47    pub fn from_bytes(bytes: &[u8]) -> Self {
48        Self {
49            key: bytes.to_vec(),
50        }
51    }
52
53    pub fn to_bytes(&self) -> &Vec<u8> {
54        &self.key
55    }
56}
57
58#[derive(Clone)]
59pub struct Argon2IdKeyProducer {
60    argon2id_params: Argon2idParams,
61    key: Vec<u8>,
62}
63
64impl Argon2IdKeyProducer {
65    pub fn get_key(&self) -> &Vec<u8> {
66        &self.key
67    }
68
69    pub fn get_parameters(&self) -> &Argon2idParams {
70        &self.argon2id_params
71    }
72
73    pub(crate) fn with_default_parameters(password: &str) -> Self {
74        Self::new(
75            password,
76            &Argon2idParams {
77                m_cost: 50 * 1024, // 50MB memory
78                t_cost: 3,         // iterations
79                p_cost: 1,         // parallelism
80                salt: get_rand_bytes(32).expect("Failed to get random bytes"),
81            },
82        )
83    }
84
85    pub fn new(password: &str, parameters: &Argon2idParams) -> Self {
86        let key = Self::derive_key(password, &parameters).expect("").to_vec();
87        let inst = Argon2IdKeyProducer {
88            argon2id_params: parameters.clone(),
89            key: key,
90        };
91        inst
92    }
93
94    fn derive_key(
95        password: &str,
96        params: &Argon2idParams,
97    ) -> Result<[u8; 32], crate::error::Error> {
98        let argon2_params = argon2::Params::new(
99            params.m_cost, // memory
100            params.t_cost, // iterations
101            params.p_cost, // parallelism
102            Some(params.salt.len()),
103        )?;
104
105        let argon2_inst = Argon2::new(
106            argon2::Algorithm::Argon2id,
107            argon2::Version::V0x13,
108            argon2_params,
109        );
110
111        let mut key = [0u8; 32];
112        argon2_inst.hash_password_into(password.as_bytes(), &params.salt, &mut key)?;
113
114        Ok(key)
115    }
116}