elastic_elgamal/keys/
mod.rs

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