elastic_elgamal/keys/
mod.rs

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