From fb91cb972e1069058209ed6954bf9cce25f0ea03 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 9 Sep 2020 07:59:48 -0700 Subject: [PATCH] elliptic-curve: remove `Generate` trait The functionality it previously provided as a trait is now available via methods like `Field::random` and `Group::random`. The other places where it was being used have been converted to inherent methods on concrete types, which is easier to use because there's no need to import a trait. --- elliptic-curve/src/ecdh.rs | 18 ++++++++-------- elliptic-curve/src/lib.rs | 9 -------- elliptic-curve/src/ops.rs | 11 +++++++++- elliptic-curve/src/scalar.rs | 36 ++++++++++++++------------------ elliptic-curve/src/secret_key.rs | 28 ++++++++++++------------- 5 files changed, 48 insertions(+), 54 deletions(-) diff --git a/elliptic-curve/src/ecdh.rs b/elliptic-curve/src/ecdh.rs index 75ea4ba85..64b29328f 100644 --- a/elliptic-curve/src/ecdh.rs +++ b/elliptic-curve/src/ecdh.rs @@ -27,7 +27,7 @@ use crate::{ scalar::NonZeroScalar, sec1::{self, FromEncodedPoint, UncompressedPointSize, UntaggedPointSize}, weierstrass::Curve, - Arithmetic, ElementBytes, Error, Generate, + Arithmetic, ElementBytes, Error, }; use core::ops::{Add, Mul}; use rand_core::{CryptoRng, RngCore}; @@ -45,7 +45,7 @@ pub type PublicKey = sec1::EncodedPoint; pub struct EphemeralSecret where C: Curve + Arithmetic, - C::Scalar: Generate + Zeroize, + C::Scalar: Zeroize, { scalar: NonZeroScalar, } @@ -53,15 +53,15 @@ where impl EphemeralSecret where C: Curve + Arithmetic, - C::Scalar: Clone + Generate + Zeroize, + C::Scalar: Clone + Zeroize, C::AffinePoint: FromEncodedPoint + Mul, Output = C::AffinePoint> + Zeroize, PublicKey: From, UntaggedPointSize: Add + ArrayLength, UncompressedPointSize: ArrayLength, { - /// Generate a new [`EphemeralSecret`]. - pub fn generate(rng: impl CryptoRng + RngCore) -> Self { - let scalar = NonZeroScalar::generate(rng); + /// Generate a cryptographically random [`EphemeralSecret`]. + pub fn random(rng: impl CryptoRng + RngCore) -> Self { + let scalar = NonZeroScalar::random(rng); Self { scalar } } @@ -89,7 +89,7 @@ where impl From<&EphemeralSecret> for PublicKey where C: Curve + Arithmetic, - C::Scalar: Clone + Generate + Zeroize, + C::Scalar: Clone + Zeroize, C::AffinePoint: FromEncodedPoint + Mul, Output = C::AffinePoint> + Zeroize, PublicKey: From, UntaggedPointSize: Add + ArrayLength, @@ -103,7 +103,7 @@ where impl Zeroize for EphemeralSecret where C: Curve + Arithmetic, - C::Scalar: Generate + Zeroize, + C::Scalar: Zeroize, { fn zeroize(&mut self) { self.scalar.zeroize() @@ -113,7 +113,7 @@ where impl Drop for EphemeralSecret where C: Curve + Arithmetic, - C::Scalar: Generate + Zeroize, + C::Scalar: Zeroize, { fn drop(&mut self) { self.zeroize(); diff --git a/elliptic-curve/src/lib.rs b/elliptic-curve/src/lib.rs index 2de20f477..576c7d4ad 100644 --- a/elliptic-curve/src/lib.rs +++ b/elliptic-curve/src/lib.rs @@ -66,7 +66,6 @@ pub use zeroize; use core::{fmt::Debug, ops::Add}; use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; -use rand_core::{CryptoRng, RngCore}; use subtle::{ConditionallySelectable, CtOption}; #[cfg(feature = "arithmetic")] @@ -124,14 +123,6 @@ pub trait FromBytes: ConditionallySelectable + Sized { fn from_bytes(bytes: &GenericArray) -> CtOption; } -/// Randomly generate a value. -/// -/// Primarily intended for use with scalar types for a particular curve. -pub trait Generate { - /// Generate a random element of this type using the provided [`CryptoRng`] - fn generate(rng: impl CryptoRng + RngCore) -> Self; -} - /// Instantiate this type from the output of a digest. /// /// This can be used for implementing hash-to-scalar (e.g. as in ECDSA) or diff --git a/elliptic-curve/src/ops.rs b/elliptic-curve/src/ops.rs index f499c01de..fe6ffe75c 100644 --- a/elliptic-curve/src/ops.rs +++ b/elliptic-curve/src/ops.rs @@ -1,6 +1,6 @@ //! Traits for arithmetic operations on elliptic curve field elements -pub use core::ops::{Add, Mul}; +pub use core::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign}; use subtle::CtOption; @@ -12,3 +12,12 @@ pub trait Invert { /// Invert a field element. fn invert(&self) -> CtOption; } + +#[cfg(feature = "arithmetic")] +impl Invert for F { + type Output = F; + + fn invert(&self) -> CtOption { + ff::Field::invert(self) + } +} diff --git a/elliptic-curve/src/scalar.rs b/elliptic-curve/src/scalar.rs index ba5411497..924073b25 100644 --- a/elliptic-curve/src/scalar.rs +++ b/elliptic-curve/src/scalar.rs @@ -3,10 +3,11 @@ use crate::{ ops::Invert, rand_core::{CryptoRng, RngCore}, - Arithmetic, Curve, ElementBytes, FromBytes, Generate, + Arithmetic, Curve, ElementBytes, FromBytes, }; use bitvec::{array::BitArray, order::Lsb0}; use core::ops::Deref; +use ff::Field; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; #[cfg(feature = "zeroize")] @@ -32,6 +33,18 @@ impl NonZeroScalar where C: Curve + Arithmetic, { + /// Generate a random `NonZeroScalar` + pub fn random(mut rng: impl CryptoRng + RngCore) -> Self { + // Use rejection sampling to eliminate zero values + loop { + let result = Self::new(C::Scalar::random(&mut rng)); + + if result.is_some().into() { + break result.unwrap(); + } + } + } + /// Create a [`NonZeroScalar`] from a scalar, performing a constant-time /// check that it's non-zero. pub fn new(scalar: C::Scalar) -> CtOption { @@ -103,28 +116,11 @@ where C: Curve + Arithmetic, C::Scalar: Invert, { - type Output = ::Output; + type Output = C::Scalar; /// Perform a scalar inversion fn invert(&self) -> CtOption { - self.scalar.invert() - } -} - -impl Generate for NonZeroScalar -where - C: Curve + Arithmetic, - C::Scalar: Generate, -{ - fn generate(mut rng: impl CryptoRng + RngCore) -> Self { - // Use rejection sampling to eliminate zero values - loop { - let result = Self::new(C::Scalar::generate(&mut rng)); - - if result.is_some().into() { - break result.unwrap(); - } - } + ff::Field::invert(&self.scalar) } } diff --git a/elliptic-curve/src/secret_key.rs b/elliptic-curve/src/secret_key.rs index 76f57ef18..1bf80d3f6 100644 --- a/elliptic-curve/src/secret_key.rs +++ b/elliptic-curve/src/secret_key.rs @@ -15,7 +15,7 @@ use core::{ use generic_array::{typenum::Unsigned, GenericArray}; #[cfg(feature = "arithmetic")] -use crate::{scalar::NonZeroScalar, Arithmetic, Generate}; +use crate::{scalar::NonZeroScalar, Arithmetic}; #[cfg(feature = "arithmetic")] use rand_core::{CryptoRng, RngCore}; @@ -31,6 +31,18 @@ pub struct SecretKey { } impl SecretKey { + /// Generate a random [`SecretKey`] + #[cfg(feature = "arithmetic")] + #[cfg_attr(docsrs, doc(cfg(feature = "arithmetic")))] + pub fn random(rng: impl CryptoRng + RngCore) -> Self + where + C: Arithmetic, + { + Self { + scalar: NonZeroScalar::::random(rng).into(), + } + } + /// Create a new secret key from a serialized scalar value pub fn new(bytes: ElementBytes) -> Self { Self { scalar: bytes } @@ -67,20 +79,6 @@ impl Debug for SecretKey { } } -#[cfg(feature = "arithmetic")] -impl Generate for SecretKey -where - C: Curve + Arithmetic, - C::Scalar: Generate + Into>, -{ - /// Generate a new [`SecretKey`] - fn generate(rng: impl CryptoRng + RngCore) -> Self { - Self { - scalar: NonZeroScalar::::generate(rng).into(), - } - } -} - #[cfg(feature = "zeroize")] impl Drop for SecretKey { fn drop(&mut self) {