1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
//! Static key operations for proving identity

use clear_on_drop::clear::Clear;
use hmac::Hmac;
use pbkdf2::pbkdf2;
use sha2::Sha256;

use super::KEY_SIZE;

/// Static identity keys from which session keys are derived
pub struct IdentityKeys {
    // Static encryption key (K-ENC)
    pub(crate) enc_key: [u8; KEY_SIZE],

    // Static MAC key (K-MAC)
    pub(crate) mac_key: [u8; KEY_SIZE],
}

impl IdentityKeys {
    /// Derive identity keys from a password
    pub fn derive_from_password(password: &[u8], salt: &[u8], iterations: usize) -> Self {
        let mut kdf_output = [0u8; KEY_SIZE * 2];
        pbkdf2::<Hmac<Sha256>>(password, salt, iterations, &mut kdf_output);

        let keys = Self::new(&kdf_output);
        kdf_output.clear();

        keys
    }

    /// Create a new keypair from a byte array
    pub fn new(key_bytes: &[u8; KEY_SIZE * 2]) -> Self {
        let mut enc_key = [0u8; KEY_SIZE];
        enc_key.copy_from_slice(&key_bytes[..KEY_SIZE]);

        let mut mac_key = [0u8; KEY_SIZE];
        mac_key.copy_from_slice(&key_bytes[KEY_SIZE..]);

        Self { enc_key, mac_key }
    }
}

impl Drop for IdentityKeys {
    fn drop(&mut self) {
        self.enc_key.clear();
        self.mac_key.clear();
    }
}