rwarden_crypto/
master_password_hash.rs

1use crate::{KdfType, SourceKey};
2use hmac::Hmac;
3use pbkdf2::pbkdf2;
4use serde::{Serialize, Serializer};
5use sha2::Sha256;
6use std::fmt;
7
8/// A hashed master password.
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct MasterPasswordHash(pub [u8; 32]);
11
12impl MasterPasswordHash {
13    /// Creates a new [`MasterPasswordHash`].
14    pub fn new<P>(source_key: &SourceKey, password: P, kdf_type: KdfType) -> Self
15    where
16        P: AsRef<[u8]>,
17    {
18        match kdf_type {
19            KdfType::Pbkdf2Sha256 => {
20                let mut master_password_hash = [0; 32];
21                pbkdf2::<Hmac<Sha256>>(
22                    &source_key.0,
23                    password.as_ref(),
24                    1,
25                    &mut master_password_hash,
26                );
27                Self(master_password_hash)
28            }
29        }
30    }
31
32    /// Encodes the master password hash as base64.
33    pub fn encode(&self) -> String {
34        base64::encode(self.0)
35    }
36}
37
38impl fmt::Display for MasterPasswordHash {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        f.write_str(&self.encode())
41    }
42}
43
44impl Serialize for MasterPasswordHash {
45    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
46    where
47        S: Serializer,
48    {
49        serializer.serialize_str(&self.to_string())
50    }
51}