From fbb167ccd91fa3811bfd5624124ca55b4c145991 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 3 Dec 2021 11:38:36 -0700 Subject: [PATCH] elliptic-curve: add `ReduceNonZero` trait Adds a trait similar to `Reduce`, but where the output of the reduction is ensured to be non-zero. Also impls `Reduce` and `ReduceNonZero` for `NonZeroScalar`. This means that end users need only concern themselves with `Reduce` as they can use `NonZeroScalar::::from_uint_reduced` instead of the more cumbersome `Scalar::::from_uint_reduced_non_zero`. Related: RustCrypto/elliptic-curves#432 --- elliptic-curve/src/ops.rs | 10 ++++++++++ elliptic-curve/src/scalar/non_zero.rs | 27 ++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index fb69b28fa..f4449a723 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -40,3 +40,13 @@ pub trait Reduce: Sized { Self::from_uint_reduced(UInt::from_le_byte_array(bytes)) } } + +/// Modular reduction to a non-zero output. +/// +/// This trait is primarily intended for use by curve implementations. +/// +/// End users can use the `Reduce` impl on `NonZeroScalar` instead. +pub trait ReduceNonZero: Sized { + /// Perform a modular reduction, returning a field element. + fn from_uint_reduced_non_zero(n: UInt) -> Self; +} diff --git a/elliptic-curve/src/scalar/non_zero.rs b/elliptic-curve/src/scalar/non_zero.rs index 5e54f942d..ab5f9084a 100644 --- a/elliptic-curve/src/scalar/non_zero.rs +++ b/elliptic-curve/src/scalar/non_zero.rs @@ -3,7 +3,7 @@ use crate::{ bigint::Encoding as _, hex, - ops::Invert, + ops::{Invert, Reduce, ReduceNonZero}, rand_core::{CryptoRng, RngCore}, Curve, Error, FieldBytes, IsHigh, Result, Scalar, ScalarArithmetic, ScalarCore, SecretKey, }; @@ -12,6 +12,7 @@ use core::{ ops::{Deref, Neg}, str, }; +use crypto_bigint::{ArrayEncoding, Integer}; use ff::{Field, PrimeField}; use generic_array::GenericArray; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -198,6 +199,30 @@ where } } +impl Reduce for NonZeroScalar +where + C: Curve + ScalarArithmetic, + I: Integer + ArrayEncoding, + Scalar: ReduceNonZero, +{ + fn from_uint_reduced(n: I) -> Self { + Self::from_uint_reduced_non_zero(n) + } +} + +impl ReduceNonZero for NonZeroScalar +where + C: Curve + ScalarArithmetic, + I: Integer + ArrayEncoding, + Scalar: ReduceNonZero, +{ + fn from_uint_reduced_non_zero(n: I) -> Self { + let scalar = Scalar::::from_uint_reduced_non_zero(n); + debug_assert!(!bool::from(scalar.is_zero())); + Self::new(scalar).unwrap() + } +} + impl TryFrom<&[u8]> for NonZeroScalar where C: Curve + ScalarArithmetic,