Skip to main content

generic_ec/non_zero/
mod.rs

1use core::{
2    cmp,
3    iter::{self, Product, Sum},
4};
5
6use rand_core::{CryptoRng, RngCore};
7use subtle::{ConstantTimeEq, CtOption};
8
9use crate::{
10    as_raw::FromRaw,
11    core::{ByteArray, FromUniformBytes},
12    errors::{ZeroPoint, ZeroScalar},
13    Curve, Point, Scalar, SecretPoint, SecretScalar,
14};
15
16use self::definition::NonZero;
17
18pub mod coords;
19pub mod definition;
20
21impl<E: Curve> NonZero<Point<E>> {
22    /// Constructs non-zero point
23    ///
24    /// Returns `None` if point is zero
25    pub fn from_point(point: Point<E>) -> Option<Self> {
26        Self::ct_from_point(point).into()
27    }
28
29    /// Constructs non-zero point (constant time)
30    ///
31    /// Returns `None` if point is zero
32    pub fn ct_from_point(point: Point<E>) -> CtOption<Self> {
33        let zero = Point::zero();
34        let is_non_zero = !point.ct_eq(&zero);
35
36        // Correctness: although we technically construct `NonZero` regardless if
37        // it's actually non-zero, `CtOption` never exposes it, so `NonZero` with
38        // zero value is not accessible by anyone
39        CtOption::new(Self::new_unchecked(point), is_non_zero)
40    }
41
42    /// Convert this value into a `NonZero<SecretPoint<E>>`. You should do this at the end
43    /// of computations that produce a secret, like a key exchange
44    #[inline(always)] // Prevent a byte copy in most cases
45    pub fn into_secret(self) -> NonZero<SecretPoint<E>> {
46        let mut point = self.into_inner();
47        let secret_point = SecretPoint::new(&mut point);
48        // Correctness: `point` was checked to be nonzero
49        NonZero::new_unchecked(secret_point)
50    }
51}
52
53impl<E: Curve> NonZero<SecretPoint<E>> {
54    /// Returns the generator defined in the curve specs
55    pub fn generator() -> Self {
56        // Correctness: generator of a non-degenerate group is not zero
57        Self::new_unchecked(SecretPoint::generator())
58    }
59
60    /// Constructs non-zero point
61    ///
62    /// Returns `None` if point is zero
63    pub fn from_secret_point(point: SecretPoint<E>) -> Option<Self> {
64        Self::ct_from_secret_point(point).into()
65    }
66
67    /// Constructs non-zero point (constant time)
68    ///
69    /// Returns `None` if point is zero
70    pub fn ct_from_secret_point(secret_point: SecretPoint<E>) -> CtOption<Self> {
71        let zero = Point::zero();
72        let is_non_zero = !secret_point.as_ref().ct_eq(&zero);
73
74        // Correctness: although we technically construct `NonZero` regardless if
75        // it's actually non-zero, `CtOption` never exposes it, so `NonZero` with
76        // zero value is not accessible by anyone
77        CtOption::new(Self::new_unchecked(secret_point), is_non_zero)
78    }
79}
80
81impl<E: Curve> NonZero<Scalar<E>> {
82    #[doc = include_str!("../../docs/nonzero_scalar_random.md")]
83    pub fn random<R: RngCore>(rng: &mut R) -> Self {
84        match iter::repeat_with(|| {
85            let mut bytes = <<E::Scalar as FromUniformBytes>::Bytes as ByteArray>::zeroes();
86            rng.fill_bytes(bytes.as_mut());
87            <E::Scalar as FromUniformBytes>::from_uniform_bytes(&bytes)
88        })
89        .take(100)
90        .flat_map(|s| NonZero::from_scalar(Scalar::from_raw(s)))
91        .next()
92        {
93            Some(s) => s,
94            None => panic!("defected source of randomness"),
95        }
96    }
97
98    #[doc = include_str!("../../docs/nonzero_scalar_random_vartime.md")]
99    pub fn random_vartime<R: RngCore>(rng: &mut R) -> Self {
100        match iter::repeat_with(|| {
101            <E::Scalar as generic_ec_core::SamplableVartime>::random_vartime(rng)
102        })
103        .take(100)
104        .flat_map(|s| NonZero::from_scalar(Scalar::from_raw(s)))
105        .next()
106        {
107            Some(s) => s,
108            None => panic!("defected source of randomness"),
109        }
110    }
111
112    #[doc = include_str!("../../docs/hash_to_scalar.md")]
113    ///
114    /// ## Example
115    /// ```rust
116    /// use generic_ec::{Scalar, NonZero, curves::Secp256k1};
117    /// use sha2::Sha256;
118    ///
119    /// #[derive(udigest::Digestable)]
120    /// struct Data<'a> {
121    ///     nonce: &'a [u8],
122    ///     param_a: &'a str,
123    ///     param_b: u128,
124    ///     // ...
125    /// }
126    ///
127    /// let scalar = NonZero::<Scalar<Secp256k1>>::from_hash::<Sha256>(&Data {
128    ///     nonce: b"some data",
129    ///     param_a: "some other data",
130    ///     param_b: 12345,
131    ///     // ...
132    /// });
133    /// ```
134    #[cfg(feature = "hash-to-scalar")]
135    pub fn from_hash<D: digest::Digest>(data: &impl udigest::Digestable) -> Self {
136        let mut rng = rand_hash::HashRng::<D, _>::from_seed(data);
137        Self::random(&mut rng)
138    }
139
140    /// Constructs $S = 1$
141    pub fn one() -> Self {
142        // Correctness: constructed scalar = 1, so it's non-zero
143        Self::new_unchecked(Scalar::one())
144    }
145
146    /// Constructs non-zero scalar
147    ///
148    /// Returns `None` if scalar is zero
149    pub fn from_scalar(scalar: Scalar<E>) -> Option<Self> {
150        Self::ct_from_scalar(scalar).into()
151    }
152
153    /// Constructs non-zero scalar (constant time)
154    ///
155    /// Returns `None` if scalar is zero
156    pub fn ct_from_scalar(scalar: Scalar<E>) -> CtOption<Self> {
157        let zero = Scalar::zero();
158        let is_non_zero = !scalar.ct_eq(&zero);
159
160        // Correctness: although we technically construct `NonZero` regardless if
161        // it's actually non-zero, `CtOption` never exposes it, so `NonZero` with
162        // zero value is not accessible by anyone
163        CtOption::new(Self::new_unchecked(scalar), is_non_zero)
164    }
165
166    /// Returns scalar inverse $S^{-1}$
167    ///
168    /// Similar to [Scalar::invert], but this function is always defined as inverse is defined for all
169    /// non-zero scalars
170    pub fn invert(&self) -> NonZero<Scalar<E>> {
171        #[allow(clippy::expect_used)]
172        let inv = (**self)
173            .invert()
174            .expect("nonzero scalar always has an invert");
175        // Correctness: `inv` is nonzero by definition
176        Self::new_unchecked(inv)
177    }
178
179    /// Upgrades the non-zero scalar into non-zero [`SecretScalar`]
180    #[inline(always)] // Prevent a byte copy in most cases
181    pub fn into_secret(self) -> NonZero<SecretScalar<E>> {
182        let mut scalar = self.into_inner();
183        let secret_scalar = SecretScalar::new(&mut scalar);
184        // Correctness: `scalar` was checked to be nonzero
185        NonZero::new_unchecked(secret_scalar)
186    }
187}
188
189impl<E: Curve> NonZero<SecretScalar<E>> {
190    #[doc = include_str!("../../docs/nonzero_scalar_random.md")]
191    pub fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
192        <Self as crate::traits::Samplable>::random(rng)
193    }
194
195    #[doc = include_str!("../../docs/nonzero_scalar_random_vartime.md")]
196    pub fn random_vartime<R: RngCore + CryptoRng>(rng: &mut R) -> Self {
197        <Self as crate::traits::Samplable>::random_vartime(rng)
198    }
199
200    /// Constructs $S = 1$
201    pub fn one() -> Self {
202        // Correctness: constructed scalar = 1, so it's non-zero
203        Self::new_unchecked(SecretScalar::one())
204    }
205
206    /// Constructs non-zero scalar
207    ///
208    /// Returns `None` if scalar is zero
209    pub fn from_secret_scalar(scalar: SecretScalar<E>) -> Option<Self> {
210        Self::ct_from_secret_scalar(scalar).into()
211    }
212
213    /// Constructs non-zero scalar (constant time)
214    ///
215    /// Returns `None` if scalar is zero
216    pub fn ct_from_secret_scalar(secret_scalar: SecretScalar<E>) -> CtOption<Self> {
217        let zero = Scalar::zero();
218        let is_non_zero = !secret_scalar.as_ref().ct_eq(&zero);
219
220        // Correctness: although we technically construct `NonZero` regardless if
221        // it's actually non-zero, `CtOption` never exposes it, so `NonZero` with
222        // zero value is not accessible by anyone
223        CtOption::new(Self::new_unchecked(secret_scalar), is_non_zero)
224    }
225
226    /// Returns scalar inverse $S^{-1}$
227    ///
228    /// Similar to [SecretScalar::invert], but this function is always defined as inverse is defined for all
229    /// non-zero scalars
230    pub fn invert(&self) -> NonZero<SecretScalar<E>> {
231        #[allow(clippy::expect_used)]
232        let inv = (**self)
233            .invert()
234            .expect("nonzero scalar always has an invert");
235        // Correctness: `inv` is nonzero by definition
236        Self::new_unchecked(inv)
237    }
238}
239
240impl<E: Curve> From<NonZero<Point<E>>> for Point<E> {
241    fn from(point: NonZero<Point<E>>) -> Self {
242        point.into_inner()
243    }
244}
245
246impl<E: Curve> From<NonZero<SecretPoint<E>>> for SecretPoint<E> {
247    fn from(secret_point: NonZero<SecretPoint<E>>) -> Self {
248        secret_point.into_inner()
249    }
250}
251
252impl<E: Curve> From<NonZero<Scalar<E>>> for Scalar<E> {
253    fn from(scalar: NonZero<Scalar<E>>) -> Self {
254        scalar.into_inner()
255    }
256}
257
258impl<E: Curve> From<NonZero<SecretScalar<E>>> for SecretScalar<E> {
259    fn from(secret_scalar: NonZero<SecretScalar<E>>) -> Self {
260        secret_scalar.into_inner()
261    }
262}
263
264impl<E: Curve> TryFrom<Point<E>> for NonZero<Point<E>> {
265    type Error = ZeroPoint;
266
267    fn try_from(point: Point<E>) -> Result<Self, Self::Error> {
268        Self::from_point(point).ok_or(ZeroPoint)
269    }
270}
271
272impl<E: Curve> TryFrom<SecretPoint<E>> for NonZero<SecretPoint<E>> {
273    type Error = ZeroPoint;
274
275    fn try_from(secret_point: SecretPoint<E>) -> Result<Self, Self::Error> {
276        Self::from_secret_point(secret_point).ok_or(ZeroPoint)
277    }
278}
279
280impl<E: Curve> TryFrom<Scalar<E>> for NonZero<Scalar<E>> {
281    type Error = ZeroScalar;
282
283    fn try_from(scalar: Scalar<E>) -> Result<Self, Self::Error> {
284        Self::from_scalar(scalar).ok_or(ZeroScalar)
285    }
286}
287
288impl<E: Curve> TryFrom<SecretScalar<E>> for NonZero<SecretScalar<E>> {
289    type Error = ZeroScalar;
290
291    fn try_from(secret_scalar: SecretScalar<E>) -> Result<Self, Self::Error> {
292        Self::from_secret_scalar(secret_scalar).ok_or(ZeroScalar)
293    }
294}
295
296impl<E: Curve> Sum<NonZero<Scalar<E>>> for Scalar<E> {
297    fn sum<I: Iterator<Item = NonZero<Scalar<E>>>>(iter: I) -> Self {
298        iter.fold(Scalar::zero(), |acc, x| acc + x)
299    }
300}
301
302impl<'s, E: Curve> Sum<&'s NonZero<Scalar<E>>> for Scalar<E> {
303    fn sum<I: Iterator<Item = &'s NonZero<Scalar<E>>>>(iter: I) -> Self {
304        iter.fold(Scalar::zero(), |acc, x| acc + x)
305    }
306}
307
308impl<'s, E: Curve> Sum<&'s NonZero<SecretScalar<E>>> for SecretScalar<E> {
309    fn sum<I: Iterator<Item = &'s NonZero<SecretScalar<E>>>>(iter: I) -> Self {
310        let mut out = Scalar::zero();
311        iter.for_each(|x| out += x);
312        SecretScalar::new(&mut out)
313    }
314}
315
316impl<E: Curve> Sum<NonZero<SecretScalar<E>>> for SecretScalar<E> {
317    fn sum<I: Iterator<Item = NonZero<SecretScalar<E>>>>(iter: I) -> Self {
318        let mut out = Scalar::zero();
319        iter.for_each(|x| out += x);
320        SecretScalar::new(&mut out)
321    }
322}
323
324impl<E: Curve> Product<NonZero<Scalar<E>>> for NonZero<Scalar<E>> {
325    fn product<I: Iterator<Item = NonZero<Scalar<E>>>>(iter: I) -> Self {
326        iter.fold(Self::one(), |acc, x| acc * x)
327    }
328}
329
330impl<'s, E: Curve> Product<&'s NonZero<Scalar<E>>> for NonZero<Scalar<E>> {
331    fn product<I: Iterator<Item = &'s NonZero<Scalar<E>>>>(iter: I) -> Self {
332        iter.fold(Self::one(), |acc, x| acc * x)
333    }
334}
335
336impl<'s, E: Curve> Product<&'s NonZero<SecretScalar<E>>> for NonZero<SecretScalar<E>> {
337    fn product<I: Iterator<Item = &'s NonZero<SecretScalar<E>>>>(iter: I) -> Self {
338        let mut out = NonZero::<Scalar<E>>::one();
339        iter.for_each(|x| out *= x);
340        out.into_secret()
341    }
342}
343
344impl<E: Curve> Product<NonZero<SecretScalar<E>>> for NonZero<SecretScalar<E>> {
345    fn product<I: Iterator<Item = NonZero<SecretScalar<E>>>>(iter: I) -> Self {
346        let mut out = NonZero::<Scalar<E>>::one();
347        iter.for_each(|x| out *= x);
348        out.into_secret()
349    }
350}
351
352impl<E: Curve> Sum<NonZero<Point<E>>> for Point<E> {
353    fn sum<I: Iterator<Item = NonZero<Point<E>>>>(iter: I) -> Self {
354        iter.fold(Point::zero(), |acc, x| acc + x)
355    }
356}
357impl<'s, E: Curve> Sum<&'s NonZero<Point<E>>> for Point<E> {
358    fn sum<I: Iterator<Item = &'s NonZero<Point<E>>>>(iter: I) -> Self {
359        iter.fold(Point::zero(), |acc, x| acc + x)
360    }
361}
362
363impl<E: Curve> Sum<NonZero<SecretPoint<E>>> for SecretPoint<E> {
364    fn sum<I: Iterator<Item = NonZero<SecretPoint<E>>>>(iter: I) -> Self {
365        let mut out = Point::zero();
366        iter.for_each(|x| out += x);
367        SecretPoint::new(&mut out)
368    }
369}
370impl<'s, E: Curve> Sum<&'s NonZero<SecretPoint<E>>> for SecretPoint<E> {
371    fn sum<I: Iterator<Item = &'s NonZero<SecretPoint<E>>>>(iter: I) -> Self {
372        let mut out = Point::zero();
373        iter.for_each(|x| out += x);
374        SecretPoint::new(&mut out)
375    }
376}
377
378impl<E: Curve> crate::traits::Samplable for NonZero<Scalar<E>> {
379    fn random<R: RngCore>(rng: &mut R) -> Self {
380        Self::random(rng)
381    }
382
383    fn random_vartime<R: rand_core::RngCore>(rng: &mut R) -> Self {
384        Self::random_vartime(rng)
385    }
386}
387
388impl<E: Curve> crate::traits::Samplable for NonZero<SecretScalar<E>> {
389    fn random<R: RngCore>(rng: &mut R) -> Self {
390        NonZero::<Scalar<E>>::random(rng).into_secret()
391    }
392
393    fn random_vartime<R: rand_core::RngCore>(rng: &mut R) -> Self {
394        NonZero::<Scalar<E>>::random_vartime(rng).into_secret()
395    }
396}
397
398impl<T> crate::traits::IsZero for NonZero<T> {
399    /// Returns `false` as `NonZero<T>` cannot be zero
400    #[inline(always)]
401    fn is_zero(&self) -> bool {
402        false
403    }
404}
405
406impl<E: Curve> crate::traits::One for NonZero<Scalar<E>> {
407    fn one() -> Self {
408        Self::one()
409    }
410
411    fn is_one(x: &Self) -> subtle::Choice {
412        x.ct_eq(&Self::one())
413    }
414}
415
416impl<E: Curve> AsRef<Point<E>> for NonZero<SecretPoint<E>> {
417    fn as_ref(&self) -> &Point<E> {
418        let secret_point: &SecretPoint<E> = self.as_ref();
419        secret_point.as_ref()
420    }
421}
422
423impl<E: Curve> AsRef<Scalar<E>> for NonZero<SecretScalar<E>> {
424    fn as_ref(&self) -> &Scalar<E> {
425        let secret_scalar: &SecretScalar<E> = self.as_ref();
426        secret_scalar.as_ref()
427    }
428}
429
430impl<T> cmp::PartialEq<T> for NonZero<T>
431where
432    T: cmp::PartialEq,
433{
434    fn eq(&self, other: &T) -> bool {
435        self.as_ref() == other
436    }
437}
438
439impl<T> cmp::PartialOrd<T> for NonZero<T>
440where
441    T: cmp::PartialOrd,
442{
443    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
444        self.as_ref().partial_cmp(other)
445    }
446}
447
448/// We can't write blanket implementation `impl<T> cmp::PartialEq<NonZero<T>> for T` due to
449/// the restrictions of the compiler, which implies unfortunate limitations that we can
450/// do `a == b` but we can't write `b == a` and that's not user-friendly.
451///
452/// However, we can write implementation of PartialEq/PartialOrd for specific `T` such as
453/// `Scalar<E>`, `Point<E>` and others. Moreover, we know for sure all possible `T` for which
454/// `NonZero<T>` is defined, so we use this macro to implement these traits for all possible `T`.
455macro_rules! impl_reverse_partial_eq_cmp {
456    ($($t:ty),+) => {$(
457        impl<E: Curve> cmp::PartialEq<NonZero<$t>> for $t {
458            fn eq(&self, other: &NonZero<$t>) -> bool {
459                let other: &$t = other.as_ref();
460                self == other
461            }
462        }
463        impl<E: Curve> cmp::PartialOrd<NonZero<$t>> for $t {
464            fn partial_cmp(&self, other: &NonZero<$t>) -> Option<cmp::Ordering> {
465                let other: &$t = other.as_ref();
466                self.partial_cmp(other)
467            }
468        }
469    )*};
470}
471
472// Note: not implemented for SecretScalar and SecretPoint as they don't
473// implement `PartialEq` for security reasons.
474impl_reverse_partial_eq_cmp!(Point<E>, Scalar<E>);
475
476impl<T: ConstantTimeEq> ConstantTimeEq for NonZero<T> {
477    fn ct_eq(&self, other: &Self) -> subtle::Choice {
478        self.as_ref().ct_eq(other.as_ref())
479    }
480}
481
482#[cfg(all(test, feature = "serde"))]
483mod non_zero_is_serializable {
484    use crate::{Curve, NonZero, Point, Scalar, SecretPoint, SecretScalar};
485
486    fn impls_serde<T>()
487    where
488        T: serde::Serialize + serde::de::DeserializeOwned,
489    {
490    }
491
492    #[allow(dead_code)]
493    fn ensure_non_zero_is_serde<E: Curve>() {
494        impls_serde::<NonZero<Point<E>>>();
495        impls_serde::<NonZero<SecretPoint<E>>>();
496        impls_serde::<NonZero<Scalar<E>>>();
497        impls_serde::<NonZero<SecretScalar<E>>>();
498    }
499}