ouisync/access_control/
local_secret.rs

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::crypto::{cipher::SecretKey, Password, PasswordSalt};
#[cfg(test)]
use rand::{CryptoRng, Rng};
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum LocalSecret {
    Password(Password),
    SecretKey(SecretKey),
}

#[cfg(test)]
impl LocalSecret {
    /// Generates random master secret containing a secret key.
    pub fn random() -> Self {
        Self::SecretKey(SecretKey::random())
    }

    /// Generates random master secret containing a secret key using the provided RNG.
    pub fn generate<R: Rng + CryptoRng + ?Sized>(rng: &mut R) -> Self {
        Self::SecretKey(SecretKey::generate(rng))
    }
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SetLocalSecret {
    Password(Password),
    KeyAndSalt(KeyAndSalt),
}

#[cfg(test)]
impl SetLocalSecret {
    /// Generates random secret key and salt.
    pub fn random() -> Self {
        Self::KeyAndSalt(KeyAndSalt::random())
    }
}

#[cfg(test)]
impl From<SetLocalSecret> for LocalSecret {
    fn from(local: SetLocalSecret) -> Self {
        match local {
            SetLocalSecret::Password(pwd) => Self::Password(pwd),
            SetLocalSecret::KeyAndSalt(local) => Self::SecretKey(local.key),
        }
    }
}

#[derive(Debug, Eq, PartialEq, Serialize, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
pub struct KeyAndSalt {
    pub key: SecretKey,
    pub salt: PasswordSalt,
}

#[cfg(test)]
impl KeyAndSalt {
    /// Generates random secret key and salt.
    pub fn random() -> Self {
        Self {
            key: SecretKey::random(),
            salt: SecretKey::random_salt(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn serialize_deserialize_bincode() {
        let orig = LocalSecret::Password("mellon".to_string().into());
        let expected_serialized_hex = "0000000006000000000000006d656c6c6f6e";

        let serialized = bincode::serialize(&orig).unwrap();
        assert_eq!(hex::encode(&serialized), expected_serialized_hex);

        let deserialized: LocalSecret = bincode::deserialize(&serialized).unwrap();
        assert_eq!(&deserialized, &orig);
    }

    #[test]
    fn serialize_deserialize_msgpack() {
        let orig = LocalSecret::Password("mellon".to_string().into());
        let expected_serialized_hex = "81a870617373776f7264a66d656c6c6f6e";

        let serialized = rmp_serde::to_vec(&orig).unwrap();
        assert_eq!(hex::encode(&serialized), expected_serialized_hex);

        let deserialized: LocalSecret = rmp_serde::from_slice(&serialized).unwrap();
        assert_eq!(&deserialized, &orig);
    }
}