Skip to content

Commit ffb6cf7

Browse files
authored
elliptic-curve: use crypto_common::Generate (#2173)
Adds a dependency on `crypto-common` (all curve implementations pretty much have a transitive one already) and replaces all of the RNG functionality with the new `Generate` trait (#2096), for the following types: - `NonZeroScalar` - `ScalarValue` - `SecretKey` - `ecdh::EphemeralSecret` Additionally `Generate` trait bounds have been added to the associated types for `CurveArithmetic`: `AffinePoint`, `ProjectivePoint`, `Scalar`
1 parent 52f2cd2 commit ffb6cf7

9 files changed

Lines changed: 135 additions & 123 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

elliptic-curve/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ features = ["hybrid-array", "rand_core", "subtle", "zeroize"]
2525
[dependencies]
2626
array = { package = "hybrid-array", version = "0.4", default-features = false, features = ["zeroize"] }
2727
base16ct = "1"
28+
common = { package = "crypto-common", version = "0.2.0-rc.9", features = ["rand_core"], path = "../crypto-common" }
2829
rand_core = { version = "0.10.0-rc-3", default-features = false }
2930
subtle = { version = "2.6", default-features = false }
3031
zeroize = { version = "1.7", default-features = false }
@@ -69,7 +70,7 @@ critical-section = ["basepoint-table", "once_cell/critical-section"]
6970
bits = ["arithmetic", "ff/bits"]
7071
dev = ["arithmetic", "dep:hex-literal", "pem", "pkcs8"]
7172
ecdh = ["arithmetic", "digest", "dep:hkdf"]
72-
getrandom = ["dep:getrandom", "arithmetic", "bigint/getrandom"]
73+
getrandom = ["dep:getrandom", "arithmetic", "bigint/getrandom", "common/getrandom"]
7374
group = ["dep:group", "ff"]
7475
pkcs8 = ["dep:pkcs8", "sec1"]
7576
pem = ["dep:pem-rfc7468", "alloc", "arithmetic", "pkcs8/pem", "sec1/pem"]

elliptic-curve/src/arithmetic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{
88
scalar::{FromUintUnchecked, IsHigh},
99
};
1010
use bigint::modular::Retrieve;
11+
use common::Generate;
1112
use core::fmt::Debug;
1213
use subtle::{ConditionallySelectable, ConstantTimeEq, CtOption};
1314
use zeroize::DefaultIsZeroes;
@@ -27,6 +28,7 @@ pub trait CurveArithmetic: Curve {
2728
+ DefaultIsZeroes
2829
+ Eq
2930
+ From<NonIdentity<Self::AffinePoint>>
31+
+ Generate
3032
+ PartialEq
3133
+ Sized
3234
+ Send
@@ -52,6 +54,7 @@ pub trait CurveArithmetic: Curve {
5254
+ DefaultIsZeroes
5355
+ From<Self::AffinePoint>
5456
+ From<NonIdentity<Self::ProjectivePoint>>
57+
+ Generate
5558
+ Into<Self::AffinePoint>
5659
+ LinearCombination<[(Self::ProjectivePoint, Self::Scalar)]>
5760
+ LinearCombination<[(Self::ProjectivePoint, Self::Scalar); 2]>
@@ -78,6 +81,7 @@ pub trait CurveArithmetic: Curve {
7881
+ From<NonZeroScalar<Self>>
7982
+ From<ScalarValue<Self>>
8083
+ FromUintUnchecked<Uint = Self::Uint>
84+
+ Generate
8185
+ Into<FieldBytes<Self>>
8286
+ Into<ScalarValue<Self>>
8387
+ Into<Self::Uint>

elliptic-curve/src/dev.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! the traits in this crate.
55
66
use crate::{
7-
BatchNormalize, Curve, CurveArithmetic, CurveGroup, FieldBytesEncoding, PrimeCurve,
7+
BatchNormalize, Curve, CurveArithmetic, CurveGroup, FieldBytesEncoding, Generate, PrimeCurve,
88
array::typenum::U32,
99
bigint::{Limb, Odd, U256, modular::Retrieve},
1010
ctutils,
@@ -31,6 +31,7 @@ use alloc::vec::Vec;
3131

3232
#[cfg(feature = "bits")]
3333
use ff::PrimeFieldBits;
34+
use rand_core::TryCryptoRng;
3435

3536
/// Pseudo-coordinate for fixed-based scalar mult output
3637
pub const PSEUDO_COORDINATE_FIXED_BASE_MUL: [u8; 32] =
@@ -176,6 +177,14 @@ impl PrimeFieldBits for Scalar {
176177
}
177178
}
178179

180+
impl Generate for Scalar {
181+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
182+
rng: &mut R,
183+
) -> core::result::Result<Self, R::Error> {
184+
ScalarValue::try_generate_from_rng(rng).map(Self)
185+
}
186+
}
187+
179188
impl AsRef<Scalar> for Scalar {
180189
fn as_ref(&self) -> &Scalar {
181190
self
@@ -548,6 +557,14 @@ impl From<NonIdentity<AffinePoint>> for AffinePoint {
548557
}
549558
}
550559

560+
impl Generate for AffinePoint {
561+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
562+
_rng: &mut R,
563+
) -> core::result::Result<Self, R::Error> {
564+
unimplemented!()
565+
}
566+
}
567+
551568
impl FromEncodedPoint<MockCurve> for AffinePoint {
552569
fn from_encoded_point(encoded_point: &EncodedPoint) -> ctutils::CtOption<Self> {
553570
let point = if encoded_point.is_identity() {
@@ -686,6 +703,14 @@ impl From<ProjectivePoint> for AffinePoint {
686703
}
687704
}
688705

706+
impl Generate for ProjectivePoint {
707+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
708+
_rng: &mut R,
709+
) -> core::result::Result<Self, R::Error> {
710+
unimplemented!()
711+
}
712+
}
713+
689714
impl FromEncodedPoint<MockCurve> for ProjectivePoint {
690715
fn from_encoded_point(_point: &EncodedPoint) -> ctutils::CtOption<Self> {
691716
unimplemented!();

elliptic-curve/src/ecdh.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ use crate::{
3232
AffinePoint, Curve, CurveArithmetic, CurveGroup, FieldBytes, NonZeroScalar, ProjectivePoint,
3333
PublicKey, point::AffineCoordinates,
3434
};
35+
use common::Generate;
3536
use core::{borrow::Borrow, fmt};
3637
use hkdf::Hkdf;
37-
use rand_core::TryCryptoRng;
38+
use rand_core::{CryptoRng, TryCryptoRng};
3839
use zeroize::{Zeroize, ZeroizeOnDrop};
3940

4041
/// Low-level Elliptic Curve Diffie-Hellman (ECDH) function.
@@ -71,16 +72,15 @@ where
7172

7273
/// Ephemeral Diffie-Hellman Secret.
7374
///
74-
/// These are ephemeral "secret key" values which are deliberately designed
75-
/// to avoid being persisted.
75+
/// These are ephemeral "secret key" values which are deliberately designed to avoid persistence.
7676
///
7777
/// To perform an ephemeral Diffie-Hellman exchange, do the following:
7878
///
79-
/// - Have each participant generate an [`EphemeralSecret`] value
79+
/// - Have each participant generate an [`EphemeralSecret`] value using the [`Generate`] trait
8080
/// - Compute the [`PublicKey`] for that value
8181
/// - Have each peer provide their [`PublicKey`] to their counterpart
8282
/// - Use [`EphemeralSecret`] and the other participant's [`PublicKey`]
83-
/// to compute a [`SharedSecret`] value.
83+
/// to compute a [`SharedSecret`] value using the [`EphemeralSecret::diffie_hellman`] function
8484
///
8585
/// # ⚠️ SECURITY WARNING ⚠️
8686
///
@@ -103,25 +103,21 @@ impl<C: CurveArithmetic> fmt::Debug for EphemeralSecret<C> {
103103
}
104104
}
105105

106-
impl<C> EphemeralSecret<C>
106+
impl<C> Generate for EphemeralSecret<C>
107107
where
108108
C: CurveArithmetic,
109109
{
110-
/// Generate a cryptographically random [`EphemeralSecret`].
111-
#[cfg(feature = "getrandom")]
112-
pub fn generate() -> Self {
113-
Self {
114-
scalar: NonZeroScalar::generate(),
115-
}
116-
}
117-
118-
/// Generate a cryptographically random [`EphemeralSecret`].
119-
pub fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
110+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
120111
Ok(Self {
121-
scalar: NonZeroScalar::try_from_rng(rng)?,
112+
scalar: NonZeroScalar::try_generate_from_rng(rng)?,
122113
})
123114
}
115+
}
124116

117+
impl<C> EphemeralSecret<C>
118+
where
119+
C: CurveArithmetic,
120+
{
125121
/// Get the public key associated with this ephemeral secret.
126122
///
127123
/// The `compress` flag enables point compression.
@@ -134,6 +130,14 @@ where
134130
pub fn diffie_hellman(&self, public_key: &PublicKey<C>) -> SharedSecret<C> {
135131
diffie_hellman(self.scalar, public_key.as_affine())
136132
}
133+
134+
/// DEPRECATED: Generate a cryptographically random [`EphemeralSecret`].
135+
///
136+
/// Use the [`Generate`] trait instead.
137+
#[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
138+
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
139+
Self::generate_from_rng(rng)
140+
}
137141
}
138142

139143
impl<C> From<&EphemeralSecret<C>> for PublicKey<C>

elliptic-curve/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ pub use array;
115115
pub use array::typenum::consts;
116116
pub use bigint;
117117
pub use bigint::ctutils;
118+
pub use common;
119+
pub use common::Generate;
118120
pub use rand_core;
119121
pub use subtle;
120122
pub use zeroize;

elliptic-curve/src/scalar/nonzero.rs

Lines changed: 23 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::{
77
scalar::IsHigh,
88
};
99
use base16ct::HexDisplay;
10+
use common::Generate;
1011
use core::{
1112
fmt,
1213
ops::{Deref, Mul, MulAssign, Neg},
@@ -50,45 +51,6 @@ impl<C> NonZeroScalar<C>
5051
where
5152
C: CurveArithmetic,
5253
{
53-
/// Generate a random [`NonZeroScalar`].
54-
///
55-
/// # Panics
56-
///
57-
/// If the system's cryptographically secure RNG has an internal error.
58-
#[cfg(feature = "getrandom")]
59-
pub fn generate() -> Self {
60-
// Use rejection sampling to eliminate invalid values
61-
// While this method isn't constant-time, the attacker shouldn't learn
62-
// anything about unrelated outputs so long as `rng` is a secure `CryptoRng`.
63-
loop {
64-
let mut repr = FieldBytes::<C>::default();
65-
getrandom::fill(&mut repr).expect("RNG failure");
66-
if let Some(result) = Self::from_repr(repr).into() {
67-
break result;
68-
}
69-
}
70-
}
71-
72-
/// Generate a random [`NonZeroScalar`].
73-
pub fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
74-
// Use rejection sampling to eliminate zero values.
75-
// While this method isn't constant-time, the attacker shouldn't learn
76-
// anything about unrelated outputs so long as `rng` is a secure `CryptoRng`.
77-
loop {
78-
if let Some(result) = Self::new(Scalar::<C>::try_from_rng(rng)?).into() {
79-
break Ok(result);
80-
}
81-
}
82-
}
83-
84-
/// Deprecated: Generate a random [`NonZeroScalar`].
85-
#[cfg(feature = "arithmetic")]
86-
#[deprecated(since = "0.14.0", note = "use `generate` or `try_from_rng` instead")]
87-
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
88-
let Ok(ret) = Self::try_from_rng(rng);
89-
ret
90-
}
91-
9254
/// Create a [`NonZeroScalar`] from a scalar.
9355
pub fn new(scalar: Scalar<C>) -> CtOption<Self> {
9456
CtOption::new(Self { scalar }, !scalar.is_zero())
@@ -124,6 +86,12 @@ where
12486
&*(scalars as *const [NonZeroScalar<C>] as *const [Scalar<C>])
12587
}
12688
}
89+
90+
/// Deprecated: Generate a random [`NonZeroScalar`].
91+
#[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
92+
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
93+
Self::generate_from_rng(rng)
94+
}
12795
}
12896

12997
impl<C> AsRef<Scalar<C>> for NonZeroScalar<C>
@@ -268,6 +236,22 @@ where
268236
}
269237
}
270238

239+
impl<C> Generate for NonZeroScalar<C>
240+
where
241+
C: CurveArithmetic,
242+
{
243+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
244+
// Use rejection sampling to eliminate zero values.
245+
// While this method isn't constant-time, the attacker shouldn't learn
246+
// anything about unrelated outputs so long as `rng` is a secure `CryptoRng`.
247+
loop {
248+
if let Some(result) = Self::new(Scalar::<C>::try_generate_from_rng(rng)?).into() {
249+
break Ok(result);
250+
}
251+
}
252+
}
253+
}
254+
271255
impl<C> Invert for NonZeroScalar<C>
272256
where
273257
C: CurveArithmetic,

elliptic-curve/src/scalar/value.rs

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ use crate::{
88
scalar::{FromUintUnchecked, IsHigh},
99
};
1010
use base16ct::HexDisplay;
11+
use common::Generate;
1112
use core::{
1213
cmp::Ordering,
1314
fmt,
1415
ops::{Add, AddAssign, Neg, ShrAssign, Sub, SubAssign},
1516
str,
1617
};
17-
use rand_core::CryptoRng;
18+
use rand_core::{CryptoRng, TryCryptoRng};
1819
use subtle::{
1920
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
2021
CtOption,
@@ -63,13 +64,6 @@ where
6364
/// Scalar modulus.
6465
pub const MODULUS: Odd<C::Uint> = C::ORDER;
6566

66-
/// Generate a random [`ScalarValue`].
67-
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
68-
Self {
69-
inner: C::Uint::random_mod_vartime(rng, Self::MODULUS.as_nz_ref()),
70-
}
71-
}
72-
7367
/// Create a new scalar from [`Curve::Uint`].
7468
pub fn new(uint: C::Uint) -> CtOption<Self> {
7569
CtOption::new(
@@ -123,6 +117,23 @@ where
123117
pub fn to_uint(&self) -> C::Uint {
124118
self.inner
125119
}
120+
121+
/// Deprecated: Generate a random [`ScalarValue`].
122+
#[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
123+
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
124+
Self::generate_from_rng(rng)
125+
}
126+
}
127+
128+
impl<C> From<u64> for ScalarValue<C>
129+
where
130+
C: Curve,
131+
{
132+
fn from(n: u64) -> Self {
133+
Self {
134+
inner: C::Uint::from(n),
135+
}
136+
}
126137
}
127138

128139
impl<C> FromUintUnchecked for ScalarValue<C>
@@ -136,6 +147,19 @@ where
136147
}
137148
}
138149

150+
impl<C> Generate for ScalarValue<C>
151+
where
152+
C: Curve,
153+
{
154+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(
155+
rng: &mut R,
156+
) -> core::result::Result<Self, R::Error> {
157+
Ok(Self {
158+
inner: C::Uint::try_random_mod_vartime(rng, Self::MODULUS.as_nz_ref())?,
159+
})
160+
}
161+
}
162+
139163
#[cfg(feature = "arithmetic")]
140164
impl<C> ScalarValue<C>
141165
where
@@ -264,17 +288,6 @@ where
264288
}
265289
}
266290

267-
impl<C> From<u64> for ScalarValue<C>
268-
where
269-
C: Curve,
270-
{
271-
fn from(n: u64) -> Self {
272-
Self {
273-
inner: C::Uint::from(n),
274-
}
275-
}
276-
}
277-
278291
impl<C> Add<ScalarValue<C>> for ScalarValue<C>
279292
where
280293
C: Curve,

0 commit comments

Comments
 (0)