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