tauri_plugin_matrix_svelte/stronghold/
utils.rs

1use std::path::Path;
2
3use blake2::{Blake2b512, Digest};
4use rand_chacha::ChaCha20Rng;
5use rand_core::{RngCore, SeedableRng};
6use serde::Deserialize;
7
8#[derive(Deserialize, Hash, Eq, PartialEq, Ord, PartialOrd, Clone)]
9#[serde(untagged)]
10pub enum BytesDto {
11    Text(String),
12    Raw(Vec<u8>),
13}
14
15impl AsRef<[u8]> for BytesDto {
16    fn as_ref(&self) -> &[u8] {
17        match self {
18            Self::Text(t) => t.as_ref(),
19            Self::Raw(b) => b.as_ref(),
20        }
21    }
22}
23
24impl From<BytesDto> for Vec<u8> {
25    fn from(v: BytesDto) -> Self {
26        match v {
27            BytesDto::Text(t) => t.as_bytes().to_vec(),
28            BytesDto::Raw(b) => b,
29        }
30    }
31}
32
33const HASH_LENGTH: usize = 32;
34
35pub struct KeyDerivation {}
36
37impl KeyDerivation {
38    /// Will create a key from [`password`] and a generated salt.
39    /// Salt will be generated to file [`salt_path`] or taken from it
40    /// if file already exists
41    pub fn argon2(password: &str, salt_path: &Path) -> Vec<u8> {
42        let mut salt = [0u8; HASH_LENGTH];
43        create_or_get_salt(&mut salt, salt_path);
44
45        argon2::hash_raw(password.as_bytes(), &salt, &Default::default())
46            .expect("Failed to generate hash for password")
47    }
48    pub fn blake2(password: &str, salt_path: &Path) -> Vec<u8> {
49        let mut salt = [0u8; HASH_LENGTH];
50        create_or_get_salt(&mut salt, salt_path);
51
52        let mut hasher = Blake2b512::new();
53        hasher.update(salt);
54        hasher.update(password);
55        hasher.finalize().to_vec()[..32].to_vec()
56    }
57}
58
59fn create_or_get_salt(salt: &mut [u8], salt_path: &Path) {
60    if salt_path.is_file() {
61        // Get existing salt
62        let tmp = std::fs::read(salt_path).unwrap();
63        salt.clone_from_slice(&tmp);
64    } else {
65        // Generate new salt
66        let mut gen = ChaCha20Rng::from_entropy();
67        gen.fill_bytes(salt);
68        std::fs::write(salt_path, salt).expect("Failed to write salt for Stronghold")
69    }
70}