Skip to content

Commit 27835aa

Browse files
authored
elliptic-curve: adds Scalar::try_from_rng method (#1774)
Depends: - zkcrypto/ff#126 - zkcrypto/ff#127 This is to provide an `ecdsa::SigningKey::try_from_rng` API (RustCrypto/signatures#915)
1 parent 67c5bf8 commit 27835aa

File tree

4 files changed

+32
-8
lines changed

4 files changed

+32
-8
lines changed

Cargo.lock

-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ hmac = { git = "https://github.com/RustCrypto/MACs.git" }
2929
crypto-bigint = { git = "https://github.com/RustCrypto/crypto-bigint.git" }
3030

3131
# https://github.com/zkcrypto/ff/pull/122
32-
ff = { git = "https://github.com/pinkforest/ff.git", branch = "bump-rand-core" }
32+
# https://github.com/zkcrypto/ff/pull/126
33+
# https://github.com/zkcrypto/ff/pull/127
34+
ff = { git = "https://github.com/baloo/ff.git", branch = "baloo/try_from_rng" }
3335

3436
# https://github.com/zkcrypto/group/pull/56
3537
group = { git = "https://github.com/pinkforest/group.git", branch = "bump-rand-0.9" }

elliptic-curve/src/dev.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::{
1010
error::{Error, Result},
1111
ops::{Invert, LinearCombination, MulByGenerator, Reduce, ShrAssign},
1212
point::AffineCoordinates,
13-
rand_core::RngCore,
13+
rand_core::{RngCore, TryRngCore},
1414
scalar::{FromUintUnchecked, IsHigh},
1515
sec1::{CompressedPoint, FromEncodedPoint, ToEncodedPoint},
1616
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
@@ -99,7 +99,7 @@ impl Field for Scalar {
9999
const ZERO: Self = Self(ScalarPrimitive::ZERO);
100100
const ONE: Self = Self(ScalarPrimitive::ONE);
101101

102-
fn random(mut rng: impl RngCore) -> Self {
102+
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
103103
let mut bytes = FieldBytes::default();
104104

105105
loop {
@@ -110,6 +110,17 @@ impl Field for Scalar {
110110
}
111111
}
112112

113+
fn try_from_rng<R: TryRngCore + ?Sized>(rng: &mut R) -> core::result::Result<Self, R::Error> {
114+
let mut bytes = FieldBytes::default();
115+
116+
loop {
117+
rng.try_fill_bytes(&mut bytes)?;
118+
if let Some(scalar) = Self::from_repr(bytes).into() {
119+
return Ok(scalar);
120+
}
121+
}
122+
}
123+
113124
fn is_zero(&self) -> Choice {
114125
self.0.is_zero()
115126
}

elliptic-curve/src/scalar/nonzero.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use core::{
1313
};
1414
use crypto_bigint::{ArrayEncoding, Integer};
1515
use ff::{Field, PrimeField};
16-
use rand_core::CryptoRng;
16+
use rand_core::{CryptoRng, TryCryptoRng};
1717
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
1818
use zeroize::Zeroize;
1919

@@ -47,19 +47,31 @@ where
4747
C: CurveArithmetic,
4848
{
4949
/// Generate a random `NonZeroScalar`.
50-
pub fn random<R: CryptoRng + ?Sized>(mut rng: &mut R) -> Self {
50+
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
5151
// Use rejection sampling to eliminate zero values.
5252
// While this method isn't constant-time, the attacker shouldn't learn
5353
// anything about unrelated outputs so long as `rng` is a secure `CryptoRng`.
5454
loop {
5555
// TODO: remove after `Field::random` switches to `&mut impl RngCore`
56-
#[allow(clippy::needless_borrows_for_generic_args)]
57-
if let Some(result) = Self::new(Field::random(&mut rng)).into() {
56+
if let Some(result) = Self::new(Field::random(rng)).into() {
5857
break result;
5958
}
6059
}
6160
}
6261

62+
/// Generate a random `NonZeroScalar`.
63+
pub fn try_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
64+
// Use rejection sampling to eliminate zero values.
65+
// While this method isn't constant-time, the attacker shouldn't learn
66+
// anything about unrelated outputs so long as `rng` is a secure `CryptoRng`.
67+
loop {
68+
// TODO: remove after `Field::random` switches to `&mut impl RngCore`
69+
if let Some(result) = Self::new(Scalar::<C>::try_from_rng(rng)?).into() {
70+
break Ok(result);
71+
}
72+
}
73+
}
74+
6375
/// Create a [`NonZeroScalar`] from a scalar.
6476
pub fn new(scalar: Scalar<C>) -> CtOption<Self> {
6577
CtOption::new(Self { scalar }, !scalar.is_zero())

0 commit comments

Comments
 (0)