elastic_elgamal/keys/
mod.rs

1//! Cryptographic keys for ElGamal encryption.
2
3use base64ct::{Base64UrlUnpadded, Encoding};
4use rand_core::{CryptoRng, RngCore};
5use zeroize::Zeroize;
6
7use core::{fmt, ops};
8
9use crate::{
10    alloc::{vec, Vec},
11    group::Group,
12};
13
14mod impls;
15
16/// Secret key for ElGamal encryption and related protocols. This is a thin wrapper around
17/// the [`Group`] scalar.
18pub struct SecretKey<G: Group>(G::Scalar);
19
20impl<G: Group> fmt::Debug for SecretKey<G> {
21    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
22        formatter
23            .debug_struct("SecretKey")
24            .field("public", &PublicKey::from(self))
25            .finish()
26    }
27}
28
29impl<G: Group> Clone for SecretKey<G> {
30    fn clone(&self) -> Self {
31        SecretKey(self.0)
32    }
33}
34
35impl<G: Group> Zeroize for SecretKey<G> {
36    fn zeroize(&mut self) {
37        self.0.zeroize();
38    }
39}
40
41impl<G: Group> Drop for SecretKey<G> {
42    fn drop(&mut self) {
43        self.0.zeroize();
44    }
45}
46
47impl<G: Group> SecretKey<G> {
48    pub(crate) fn new(scalar: G::Scalar) -> Self {
49        SecretKey(scalar)
50    }
51
52    /// Generates a random secret key.
53    pub fn generate<R: CryptoRng + RngCore>(rng: &mut R) -> Self {
54        SecretKey(G::generate_scalar(rng))
55    }
56
57    /// Deserializes a secret key from bytes. If bytes do not represent a valid scalar,
58    /// returns `None`.
59    pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
60        if bytes.len() != G::SCALAR_SIZE {
61            return None;
62        }
63        G::deserialize_scalar(bytes).map(SecretKey)
64    }
65
66    /// Exposes the scalar equivalent to this key.
67    pub fn expose_scalar(&self) -> &G::Scalar {
68        &self.0
69    }
70}
71
72impl<G: Group> ops::Add for SecretKey<G> {
73    type Output = Self;
74
75    fn add(self, rhs: Self) -> Self {
76        Self(self.0 + rhs.0)
77    }
78}
79
80impl<G: Group> ops::AddAssign for SecretKey<G> {
81    fn add_assign(&mut self, rhs: Self) {
82        self.0 = self.0 + rhs.0;
83    }
84}
85
86impl<G: Group> ops::Sub for SecretKey<G> {
87    type Output = Self;
88
89    fn sub(self, rhs: Self) -> Self {
90        Self(self.0 - rhs.0)
91    }
92}
93
94impl<G: Group> ops::SubAssign for SecretKey<G> {
95    fn sub_assign(&mut self, rhs: Self) {
96        self.0 = self.0 - rhs.0;
97    }
98}
99
100impl<G: Group> ops::Mul<&G::Scalar> for SecretKey<G> {
101    type Output = Self;
102
103    fn mul(self, &k: &G::Scalar) -> Self {
104        Self(self.0 * k)
105    }
106}
107
108impl<G: Group> ops::Mul<&G::Scalar> for &SecretKey<G> {
109    type Output = SecretKey<G>;
110
111    fn mul(self, &k: &G::Scalar) -> SecretKey<G> {
112        SecretKey(self.0 * k)
113    }
114}
115
116/// Public key for ElGamal encryption and related protocols.
117///
118/// # Implementation details
119///
120/// We store both the original bytes (which are used in zero-knowledge proofs)
121/// and its decompression into a [`Group`] element.
122/// This increases the memory footprint, but speeds up generating / verifying proofs.
123pub struct PublicKey<G: Group> {
124    bytes: Vec<u8>,
125    element: G::Element,
126}
127
128impl<G: Group> Clone for PublicKey<G> {
129    fn clone(&self) -> Self {
130        PublicKey {
131            bytes: self.bytes.clone(),
132            element: self.element,
133        }
134    }
135}
136
137impl<G: Group> fmt::Debug for PublicKey<G> {
138    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
139        formatter
140            .debug_tuple("PublicKey")
141            .field(&Base64UrlUnpadded::encode_string(&self.bytes))
142            .finish()
143    }
144}
145
146impl<G> PartialEq for PublicKey<G>
147where
148    G: Group,
149{
150    fn eq(&self, other: &Self) -> bool {
151        self.bytes == other.bytes
152    }
153}
154
155impl<G: Group> PublicKey<G> {
156    /// Deserializes a public key from bytes.
157    ///
158    /// # Errors
159    ///
160    /// Returns an error if `bytes` has invalid byte size, does not represent a valid group element
161    /// or represents the group identity.
162    pub fn from_bytes(bytes: &[u8]) -> Result<Self, PublicKeyConversionError> {
163        if bytes.len() != G::ELEMENT_SIZE {
164            return Err(PublicKeyConversionError::InvalidByteSize);
165        }
166
167        let element =
168            G::deserialize_element(bytes).ok_or(PublicKeyConversionError::InvalidGroupElement)?;
169        if G::is_identity(&element) {
170            Err(PublicKeyConversionError::IdentityKey)
171        } else {
172            Ok(Self {
173                bytes: bytes.to_vec(),
174                element,
175            })
176        }
177    }
178
179    pub(crate) fn from_element(element: G::Element) -> Self {
180        let mut element_bytes = vec![0_u8; G::ELEMENT_SIZE];
181        G::serialize_element(&element, &mut element_bytes);
182        PublicKey {
183            element,
184            bytes: element_bytes,
185        }
186    }
187
188    /// Returns bytes representing the group element corresponding to this key.
189    pub fn as_bytes(&self) -> &[u8] {
190        &self.bytes
191    }
192
193    /// Returns the group element equivalent to this key.
194    pub fn as_element(&self) -> G::Element {
195        self.element
196    }
197}
198
199impl<G: Group> From<&SecretKey<G>> for PublicKey<G> {
200    fn from(secret_key: &SecretKey<G>) -> Self {
201        let element = G::mul_generator(&secret_key.0);
202        Self::from_element(element)
203    }
204}
205
206/// Errors that can occur when converting other types to [`PublicKey`].
207#[derive(Debug, Clone)]
208#[non_exhaustive]
209pub enum PublicKeyConversionError {
210    /// Invalid size of the byte buffer.
211    InvalidByteSize,
212    /// Byte buffer has correct size, but does not represent a group element.
213    InvalidGroupElement,
214    /// Underlying group element is the group identity.
215    IdentityKey,
216}
217
218impl fmt::Display for PublicKeyConversionError {
219    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
220        formatter.write_str(match self {
221            Self::InvalidByteSize => "invalid size of the byte buffer",
222            Self::InvalidGroupElement => {
223                "byte buffer has correct size, but does not represent a group element"
224            }
225            Self::IdentityKey => "underlying group element is the group identity",
226        })
227    }
228}
229
230#[cfg(feature = "std")]
231impl std::error::Error for PublicKeyConversionError {}
232
233impl<G: Group> ops::Add<Self> for PublicKey<G> {
234    type Output = Self;
235
236    fn add(self, rhs: Self) -> Self {
237        let element = self.element + rhs.element;
238        Self::from_element(element)
239    }
240}
241
242impl<G: Group> ops::Mul<&G::Scalar> for PublicKey<G> {
243    type Output = Self;
244
245    fn mul(self, k: &G::Scalar) -> Self {
246        let element = self.element * k;
247        Self::from_element(element)
248    }
249}
250
251impl<G: Group> ops::Mul<u64> for PublicKey<G> {
252    type Output = Self;
253
254    fn mul(self, k: u64) -> Self {
255        self * &G::Scalar::from(k)
256    }
257}
258
259/// Keypair for ElGamal encryption and related protocols, consisting of a [`SecretKey`]
260/// and the matching [`PublicKey`].
261pub struct Keypair<G: Group> {
262    secret: SecretKey<G>,
263    public: PublicKey<G>,
264}
265
266impl<G: Group> fmt::Debug for Keypair<G> {
267    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
268        formatter
269            .debug_struct("Keypair")
270            .field("public", &self.public)
271            .finish_non_exhaustive()
272    }
273}
274
275impl<G: Group> Clone for Keypair<G> {
276    fn clone(&self) -> Self {
277        Keypair {
278            secret: self.secret.clone(),
279            public: self.public.clone(),
280        }
281    }
282}
283
284impl<G: Group> Keypair<G> {
285    /// Generates a random keypair.
286    pub fn generate<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
287        let secret = SecretKey::generate(rng);
288        Keypair {
289            public: PublicKey::from(&secret),
290            secret,
291        }
292    }
293
294    /// Returns the public part of this keypair.
295    pub fn public(&self) -> &PublicKey<G> {
296        &self.public
297    }
298
299    /// Returns the secret part of this keypair.
300    pub fn secret(&self) -> &SecretKey<G> {
301        &self.secret
302    }
303
304    /// Returns public and secret keys comprising this keypair.
305    pub fn into_tuple(self) -> (PublicKey<G>, SecretKey<G>) {
306        (self.public, self.secret)
307    }
308}
309
310impl<G: Group> From<SecretKey<G>> for Keypair<G> {
311    fn from(secret: SecretKey<G>) -> Self {
312        Self {
313            public: PublicKey::from(&secret),
314            secret,
315        }
316    }
317}
318
319impl<G: Group> ops::Mul<&G::Scalar> for Keypair<G> {
320    type Output = Self;
321
322    fn mul(self, k: &G::Scalar) -> Self {
323        Keypair {
324            secret: self.secret * k,
325            public: self.public * k,
326        }
327    }
328}