distant_net/common/transport/framed/exchange/
salt.rs

1use std::convert::{TryFrom, TryInto};
2use std::ops::BitXor;
3use std::str::FromStr;
4use std::{fmt, io};
5
6use rand::rngs::OsRng;
7use rand::RngCore;
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10/// Friendly wrapper around a 32-byte array representing a salt
11#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
12#[serde(into = "Vec<u8>", try_from = "Vec<u8>")]
13pub struct Salt([u8; 32]);
14
15impl Salt {
16    /// Generates a salt via a uniform random
17    pub fn random() -> Self {
18        let mut salt = [0u8; 32];
19        OsRng.fill_bytes(&mut salt);
20        Self(salt)
21    }
22}
23
24impl fmt::Display for Salt {
25    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26        write!(f, "{}", hex::encode(self.0))
27    }
28}
29
30impl serde_bytes::Serialize for Salt {
31    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32    where
33        S: Serializer,
34    {
35        serializer.serialize_bytes(self.as_ref())
36    }
37}
38
39impl<'de> serde_bytes::Deserialize<'de> for Salt {
40    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
41    where
42        D: Deserializer<'de>,
43    {
44        let bytes = Deserialize::deserialize(deserializer).map(serde_bytes::ByteBuf::into_vec)?;
45        let bytes_len = bytes.len();
46        Salt::try_from(bytes)
47            .map_err(|_| serde::de::Error::invalid_length(bytes_len, &"expected 32-byte length"))
48    }
49}
50
51impl From<Salt> for String {
52    fn from(salt: Salt) -> Self {
53        salt.to_string()
54    }
55}
56
57impl FromStr for Salt {
58    type Err = io::Error;
59
60    fn from_str(s: &str) -> Result<Self, Self::Err> {
61        let bytes = hex::decode(s).map_err(|x| io::Error::new(io::ErrorKind::InvalidData, x))?;
62        Self::try_from(bytes)
63    }
64}
65
66impl TryFrom<String> for Salt {
67    type Error = io::Error;
68
69    fn try_from(s: String) -> Result<Self, Self::Error> {
70        s.parse()
71    }
72}
73
74impl TryFrom<Vec<u8>> for Salt {
75    type Error = io::Error;
76
77    fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
78        Ok(Self(bytes.try_into().map_err(|x: Vec<u8>| {
79            io::Error::new(
80                io::ErrorKind::InvalidData,
81                format!("Vec<u8> len of {} != 32", x.len()),
82            )
83        })?))
84    }
85}
86
87impl From<Salt> for Vec<u8> {
88    fn from(salt: Salt) -> Self {
89        salt.0.to_vec()
90    }
91}
92
93impl AsRef<[u8]> for Salt {
94    fn as_ref(&self) -> &[u8] {
95        self.0.as_ref()
96    }
97}
98
99impl BitXor for Salt {
100    type Output = Self;
101
102    fn bitxor(self, rhs: Self) -> Self::Output {
103        let shared_salt = self
104            .0
105            .iter()
106            .zip(rhs.0.iter())
107            .map(|(x, y)| x ^ y)
108            .collect::<Vec<u8>>();
109        Self::try_from(shared_salt).unwrap()
110    }
111}