Skip to main content

generic_ec/
encoded.rs

1use core::{fmt, ops};
2
3use subtle::{Choice, ConstantTimeEq};
4use zeroize::Zeroize;
5
6use crate::{as_raw::AsRaw, core::ByteArray, secret, Curve};
7
8/// Bytes representation of an elliptic point
9#[derive(Zeroize)]
10pub struct EncodedPoint<E: Curve>(EncodedPointInner<E>);
11
12impl<E: Curve> EncodedPoint<E> {
13    pub(crate) fn new_compressed(bytes: E::CompressedPointArray) -> Self {
14        Self(EncodedPointInner::Compressed(bytes))
15    }
16
17    pub(crate) fn new_uncompressed(bytes: E::UncompressedPointArray) -> Self {
18        Self(EncodedPointInner::Uncompressed(bytes))
19    }
20
21    /// Returns bytes representation of the point
22    pub fn as_bytes(&self) -> &[u8] {
23        match &self.0 {
24            EncodedPointInner::Compressed(bytes) => bytes.as_ref(),
25            EncodedPointInner::Uncompressed(bytes) => bytes.as_ref(),
26        }
27    }
28}
29
30impl<E: Curve> Clone for EncodedPoint<E> {
31    fn clone(&self) -> Self {
32        Self(self.0.clone())
33    }
34}
35
36impl<E: Curve> Default for EncodedPoint<E> {
37    fn default() -> Self {
38        Self(EncodedPointInner::Uncompressed(
39            E::UncompressedPointArray::zeroes(),
40        ))
41    }
42}
43
44impl<E: Curve> PartialEq for EncodedPoint<E> {
45    fn eq(&self, other: &Self) -> bool {
46        self.as_bytes() == other.as_bytes()
47    }
48}
49
50impl<E: Curve> Eq for EncodedPoint<E> {}
51
52impl<E: Curve> fmt::Debug for EncodedPoint<E> {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        let mut tuple = f.debug_tuple("EncodedPoint");
55        #[cfg(feature = "alloc")]
56        {
57            tuple.field(&hex::encode(self.as_bytes()));
58        }
59        tuple.finish()
60    }
61}
62
63impl<E: Curve> ops::Deref for EncodedPoint<E> {
64    type Target = [u8];
65    fn deref(&self) -> &[u8] {
66        self.as_bytes()
67    }
68}
69
70#[derive(Clone)]
71enum EncodedPointInner<E: Curve> {
72    Compressed(E::CompressedPointArray),
73    Uncompressed(E::UncompressedPointArray),
74}
75
76impl<E: Curve> AsRef<[u8]> for EncodedPoint<E> {
77    fn as_ref(&self) -> &[u8] {
78        self.as_bytes()
79    }
80}
81
82impl<E: Curve> AsMut<[u8]> for EncodedPoint<E> {
83    fn as_mut(&mut self) -> &mut [u8] {
84        match &mut self.0 {
85            EncodedPointInner::Compressed(a) => a.as_mut(),
86            EncodedPointInner::Uncompressed(a) => a.as_mut(),
87        }
88    }
89}
90
91impl<E: Curve> Zeroize for EncodedPointInner<E> {
92    fn zeroize(&mut self) {
93        match self {
94            EncodedPointInner::Compressed(a) => a.as_mut().zeroize(),
95            EncodedPointInner::Uncompressed(a) => a.as_mut().zeroize(),
96        }
97    }
98}
99
100/// Bytes representation of a scalar (either in big-endian or in little-endian)
101#[derive(Clone)]
102pub struct EncodedScalar<E: Curve>(E::ScalarArray);
103
104impl<E: Curve> EncodedScalar<E> {
105    pub(crate) fn new(bytes: E::ScalarArray) -> Self {
106        Self(bytes)
107    }
108
109    /// Returns bytes representation of a scalar
110    pub fn as_bytes(&self) -> &[u8] {
111        self.0.as_ref()
112    }
113}
114
115impl<E: Curve> AsRef<[u8]> for EncodedScalar<E> {
116    fn as_ref(&self) -> &[u8] {
117        self.as_bytes()
118    }
119}
120
121impl<E: Curve> AsMut<[u8]> for EncodedScalar<E> {
122    fn as_mut(&mut self) -> &mut [u8] {
123        self.0.as_mut()
124    }
125}
126
127impl<E: Curve> ops::Deref for EncodedScalar<E> {
128    type Target = [u8];
129    fn deref(&self) -> &[u8] {
130        self.as_bytes()
131    }
132}
133
134impl<E: Curve> fmt::Debug for EncodedScalar<E> {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136        let mut s = f.debug_tuple("EncodedScalar");
137        #[cfg(feature = "std")]
138        {
139            s.field(&hex::encode(self.as_bytes()));
140        }
141        s.finish()
142    }
143}
144
145impl<E: Curve> PartialEq for EncodedScalar<E> {
146    fn eq(&self, other: &Self) -> bool {
147        self.as_bytes() == other.as_bytes()
148    }
149}
150
151impl<E: Curve> Eq for EncodedScalar<E> {}
152
153impl<E: Curve> Default for EncodedScalar<E> {
154    fn default() -> Self {
155        let bytes = E::ScalarArray::zeroes();
156        Self(bytes)
157    }
158}
159
160impl<E: Curve> AsRaw for EncodedScalar<E> {
161    type Raw = E::ScalarArray;
162    fn as_raw(&self) -> &Self::Raw {
163        &self.0
164    }
165}
166
167impl<E: Curve> Zeroize for EncodedScalar<E> {
168    fn zeroize(&mut self) {
169        self.as_mut().zeroize()
170    }
171}
172
173/// Bytes representation of a secret elliptic point. See [`SecretPoint`] for
174/// more information
175///
176/// This representation is automatically zeroed on drop, and doesn't implement
177/// some vartime methods. You can still access the underlying bytes by calling
178/// `.as_ref()`. This bypasses all the secrecy guarantees given by this struct.
179///
180/// [`SecretPoint`]: crate::SecretPoint
181#[derive(Clone, Default)]
182pub struct EncodedSecretPoint<E: Curve>(secret::Secret<EncodedPoint<E>>);
183
184impl<E: Curve> EncodedSecretPoint<E> {
185    /// Wrap a non-secret representation
186    #[inline(always)]
187    pub fn new(mut point: EncodedPoint<E>) -> Self {
188        Self(secret::new(&mut point))
189    }
190
191    /// Obtain the reference to the encoded bytes. This bypasses all the secrecy
192    /// guarantees, so be careful when handling them; ideally this reference should not be
193    /// held for longer than one expression
194    pub fn as_nonsecret_bytes(&self) -> &[u8] {
195        self.0.as_bytes()
196    }
197
198    /// Obtain the reference to the encoded point, which you can use as bytes
199    /// when necessary. This bypasses all the secrecy guarantees, so be careful
200    /// when handling the resulting value; ideally this reference should not be
201    /// held for longer than one expression
202    pub fn as_nonsecret(&self) -> &EncodedPoint<E> {
203        secret::inner_ref(&self.0)
204    }
205}
206
207impl<E: Curve> fmt::Debug for EncodedSecretPoint<E> {
208    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
209        f.write_str("SecretEncodedPoint")
210    }
211}
212
213impl<E: Curve> ConstantTimeEq for EncodedSecretPoint<E> {
214    fn ct_eq(&self, other: &Self) -> Choice {
215        self.0.ct_eq(&other.0)
216    }
217}
218
219/// Bytes representation of a secret elliptic scalar. See [`SecretScalar`] for
220/// more information
221///
222/// This representation is automatically zeroed on drop, and doesn't implement
223/// some vartime methods. You can still access the underlying bytes by calling
224/// `.as_ref()`. This bypasses all the secrecy guarantees given by this struct.
225///
226/// [`SecretScalar`]: crate::SecretScalar
227#[derive(Clone, Default)]
228pub struct EncodedSecretScalar<E: Curve>(secret::Secret<EncodedScalar<E>>);
229
230impl<E: Curve> EncodedSecretScalar<E> {
231    /// Wrap a non-secret representation
232    pub fn new(mut scalar: EncodedScalar<E>) -> Self {
233        Self(secret::new(&mut scalar))
234    }
235
236    /// Obtain the reference to the encoded bytes. This bypasses all the secrecy
237    /// guarantees, so be careful when handling them; ideally this reference should not be
238    /// held for longer than one expression
239    pub fn as_nonsecret_bytes(&self) -> &[u8] {
240        self.0.as_bytes()
241    }
242
243    /// Obtain the reference to the encoded scalar, which you can use as bytes
244    /// when necessary. This bypasses all the secrecy guarantees, so be careful
245    /// when handling the resulting value; ideally this reference should not be
246    /// held for longer than one expression
247    pub fn as_nonsecret(&self) -> &EncodedScalar<E> {
248        secret::inner_ref(&self.0)
249    }
250}
251
252impl<E: Curve> fmt::Debug for EncodedSecretScalar<E> {
253    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
254        f.write_str("SecretEncodedScalar")
255    }
256}
257
258impl<E: Curve> ConstantTimeEq for EncodedSecretScalar<E> {
259    fn ct_eq(&self, other: &Self) -> Choice {
260        self.0.ct_eq(&other.0)
261    }
262}