keynesis_core/key/
shared_secret.rs

1use crate::memsec::{self, Scrubbed};
2use std::{
3    cmp::Ordering,
4    fmt::{self, Debug, Formatter},
5    hash::{Hash, Hasher},
6};
7
8/// A Shared Secret that can be used to generate a symmetric key
9#[derive(Clone)]
10pub struct SharedSecret([u8; 32]);
11
12impl SharedSecret {
13    pub const SIZE: usize = 32;
14
15    /// create a shared secret from the given bytes
16    ///
17    /// To use only as a constructor if receiving the shared secret
18    /// from a HSM or a secure enclave. Otherwise use the exchange
19    /// function on the associate private/secret keys
20    pub const fn new(shared_secret: [u8; 32]) -> Self {
21        Self(shared_secret)
22    }
23}
24
25/* Format ****************************************************************** */
26
27#[cfg(test)]
28impl Debug for SharedSecret {
29    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
30        f.debug_tuple("SharedSecret<Ed25519>")
31            .field(&hex::encode(&self.0))
32            .finish()
33    }
34}
35
36#[cfg(not(test))]
37impl Debug for SharedSecret {
38    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
39        f.debug_tuple("SharedSecret<Ed25519>")
40            .field(&"...")
41            .finish()
42    }
43}
44
45/* Eq ********************************************************************** */
46
47impl PartialEq<Self> for SharedSecret {
48    fn eq(&self, other: &Self) -> bool {
49        unsafe { memsec::memeq(self.0.as_ptr(), other.0.as_ptr(), Self::SIZE) }
50    }
51}
52
53impl Eq for SharedSecret {}
54
55/* Ord ********************************************************************* */
56
57impl PartialOrd<Self> for SharedSecret {
58    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
59        Some(self.cmp(other))
60    }
61}
62
63impl Ord for SharedSecret {
64    fn cmp(&self, other: &Self) -> Ordering {
65        unsafe { memsec::memcmp(self.0.as_ptr(), other.0.as_ptr(), Self::SIZE) }
66    }
67}
68
69/* Hash ******************************************************************** */
70
71impl Hash for SharedSecret {
72    fn hash<H: Hasher>(&self, state: &mut H) {
73        self.0.as_ref().hash(state)
74    }
75}
76
77/* AsRef ******************************************************************* */
78
79impl AsRef<[u8]> for SharedSecret {
80    fn as_ref(&self) -> &[u8] {
81        self.0.as_ref()
82    }
83}
84
85/* Drop ******************************************************************** */
86
87/// custom implementation of Drop so we can have more certainty that
88/// the shared secret raw data will be scrubbed (zeroed) before releasing
89/// the memory
90impl Drop for SharedSecret {
91    fn drop(&mut self) {
92        self.0.scrub()
93    }
94}