libpep/high_level/
keys.rs

1//! Generation of global keys (only for system configuration) and session keys (only for 1-PEP),
2//! and pseudonymization and rekeying secrets to be used for transcryption.
3
4use crate::high_level::contexts::EncryptionContext;
5use crate::high_level::utils::make_rekey_factor;
6use crate::internal::arithmetic::{GroupElement, ScalarNonZero, ScalarTraits, G};
7use derive_more::{Deref, From};
8use rand_core::{CryptoRng, RngCore};
9use serde::de::{Error, Visitor};
10use serde::{Deserialize, Deserializer, Serialize, Serializer};
11use std::fmt::Formatter;
12
13/// A global public key associated with the [`GlobalSecretKey`] from which session keys are derived.
14/// Can also be used to encrypt messages against, if no session key is available or using a session
15/// key may leak information.
16#[derive(Copy, Clone, Eq, PartialEq, Debug, Deref, From, Serialize, Deserialize)]
17pub struct GlobalPublicKey(pub GroupElement);
18/// A global secret key from which session keys are derived.
19#[derive(Copy, Clone, Debug, From)]
20pub struct GlobalSecretKey(pub(crate) ScalarNonZero);
21
22/// A session public key used to encrypt messages against, associated with a [`SessionSecretKey`].
23#[derive(Copy, Clone, Eq, PartialEq, Debug, Deref, From, Serialize, Deserialize)]
24pub struct SessionPublicKey(pub GroupElement);
25/// A session secret key used to decrypt messages with.
26#[derive(Copy, Clone, Debug, From)]
27pub struct SessionSecretKey(pub(crate) ScalarNonZero);
28
29impl Serialize for SessionSecretKey {
30    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
31    where
32        S: Serializer,
33    {
34        serializer.serialize_str(self.0.encode_as_hex().as_str())
35    }
36}
37impl<'de> Deserialize<'de> for SessionSecretKey {
38    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39    where
40        D: Deserializer<'de>,
41    {
42        struct SessionSecretKeyVisitor;
43        impl Visitor<'_> for SessionSecretKeyVisitor {
44            type Value = SessionSecretKey;
45            fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
46                formatter.write_str("a hex encoded string representing a SessionSecretKey")
47            }
48
49            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
50            where
51                E: Error,
52            {
53                ScalarNonZero::decode_from_hex(v)
54                    .map(SessionSecretKey)
55                    .ok_or(E::custom(format!("invalid hex encoded string: {}", v)))
56            }
57        }
58
59        deserializer.deserialize_str(SessionSecretKeyVisitor)
60    }
61}
62
63/// A trait for public keys, which can be encoded and decoded from byte arrays and hex strings.
64pub trait PublicKey {
65    fn value(&self) -> &GroupElement;
66    fn encode(&self) -> [u8; 32] {
67        self.value().encode()
68    }
69    fn as_hex(&self) -> String {
70        self.value().encode_as_hex()
71    }
72    fn decode(bytes: &[u8; 32]) -> Option<Self>
73    where
74        Self: Sized;
75    fn decode_from_slice(slice: &[u8]) -> Option<Self>
76    where
77        Self: Sized;
78    fn from_hex(s: &str) -> Option<Self>
79    where
80        Self: Sized;
81}
82/// A trait for secret keys, for which we do not allow encoding as secret keys should not be shared.
83pub trait SecretKey {
84    fn value(&self) -> &ScalarNonZero; // TODO should this be public (or only under the `insecure-methods` feature)?
85}
86impl PublicKey for GlobalPublicKey {
87    fn value(&self) -> &GroupElement {
88        &self.0
89    }
90
91    fn decode(bytes: &[u8; 32]) -> Option<Self>
92    where
93        Self: Sized,
94    {
95        GroupElement::decode(bytes).map(Self::from)
96    }
97    fn decode_from_slice(slice: &[u8]) -> Option<Self>
98    where
99        Self: Sized,
100    {
101        GroupElement::decode_from_slice(slice).map(GlobalPublicKey::from)
102    }
103    fn from_hex(s: &str) -> Option<Self>
104    where
105        Self: Sized,
106    {
107        GroupElement::decode_from_hex(s).map(GlobalPublicKey::from)
108    }
109}
110impl SecretKey for GlobalSecretKey {
111    fn value(&self) -> &ScalarNonZero {
112        &self.0
113    }
114}
115impl PublicKey for SessionPublicKey {
116    fn value(&self) -> &GroupElement {
117        &self.0
118    }
119    fn decode(bytes: &[u8; 32]) -> Option<Self>
120    where
121        Self: Sized,
122    {
123        GroupElement::decode(bytes).map(Self::from)
124    }
125    fn decode_from_slice(slice: &[u8]) -> Option<Self>
126    where
127        Self: Sized,
128    {
129        GroupElement::decode_from_slice(slice).map(SessionPublicKey::from)
130    }
131    fn from_hex(s: &str) -> Option<Self>
132    where
133        Self: Sized,
134    {
135        GroupElement::decode_from_hex(s).map(SessionPublicKey::from)
136    }
137}
138impl SecretKey for SessionSecretKey {
139    fn value(&self) -> &ScalarNonZero {
140        &self.0
141    }
142}
143
144/// A `secret` is a byte array of arbitrary length, which is used to derive pseudonymization and rekeying factors from contexts.
145pub type Secret = Box<[u8]>;
146/// Pseudonymization secret used to derive a [`ReshuffleFactor`](crate::high_level::contexts::ReshuffleFactor) from a [`PseudonymizationContext`](crate::high_level::contexts::PseudonymizationDomain) (see [`PseudonymizationInfo`](crate::high_level::contexts::PseudonymizationInfo)).
147#[derive(Clone, Debug, From)]
148pub struct PseudonymizationSecret(pub(crate) Secret);
149/// Encryption secret used to derive a [`RekeyFactor`](crate::high_level::contexts::RekeyFactor) from an [`EncryptionContext`] (see [`RekeyInfo`](crate::high_level::contexts::RekeyInfo)).
150#[derive(Clone, Debug, From)]
151pub struct EncryptionSecret(pub(crate) Secret);
152impl PseudonymizationSecret {
153    pub fn from(secret: Vec<u8>) -> Self {
154        Self(secret.into_boxed_slice())
155    }
156}
157impl EncryptionSecret {
158    pub fn from(secret: Vec<u8>) -> Self {
159        Self(secret.into_boxed_slice())
160    }
161}
162
163/// Generate a new global key pair.
164pub fn make_global_keys<R: RngCore + CryptoRng>(rng: &mut R) -> (GlobalPublicKey, GlobalSecretKey) {
165    let sk = loop {
166        let sk = ScalarNonZero::random(rng);
167        if sk != ScalarNonZero::one() {
168            break sk;
169        }
170    };
171    let pk = sk * G;
172    (GlobalPublicKey(pk), GlobalSecretKey(sk))
173}
174
175/// Generate session keys from a [`GlobalSecretKey`], an [`EncryptionContext`] and an [`EncryptionSecret`].
176pub fn make_session_keys(
177    global: &GlobalSecretKey,
178    context: &EncryptionContext,
179    secret: &EncryptionSecret,
180) -> (SessionPublicKey, SessionSecretKey) {
181    let k = make_rekey_factor(secret, context);
182    let sk = k.0 * global.0;
183    let pk = sk * G;
184    (SessionPublicKey(pk), SessionSecretKey(sk))
185}