Skip to content

Commit 9e8656b

Browse files
daxpeddatarcieri
andauthored
Use rejection sampling for random point generation (#1344)
Co-authored-by: Tony Arcieri <[email protected]>
1 parent 912d939 commit 9e8656b

File tree

6 files changed

+64
-15
lines changed

6 files changed

+64
-15
lines changed

ed448-goldilocks/src/decaf/points.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,14 @@ impl Group for DecafPoint {
174174
where
175175
R: TryRngCore + ?Sized,
176176
{
177-
let mut uniform_bytes = [0u8; 112];
178-
rng.try_fill_bytes(&mut uniform_bytes)?;
179-
Ok(Self::from_uniform_bytes(&uniform_bytes))
177+
let mut bytes = DecafPointRepr::default();
178+
179+
loop {
180+
rng.try_fill_bytes(bytes.as_mut())?;
181+
if let Some(point) = Self::from_bytes(&bytes).into() {
182+
return Ok(point);
183+
}
184+
}
180185
}
181186

182187
fn identity() -> Self {

ed448-goldilocks/src/edwards/extended.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,14 @@ impl Group for EdwardsPoint {
341341
where
342342
R: TryRngCore + ?Sized,
343343
{
344-
let mut bytes = [0u8; 32];
345-
rng.try_fill_bytes(&mut bytes)?;
346-
Ok(Self::hash_with_defaults(&bytes))
344+
let mut bytes = Array::default();
345+
346+
loop {
347+
rng.try_fill_bytes(bytes.as_mut())?;
348+
if let Some(point) = Self::from_bytes(&bytes).into() {
349+
return Ok(point);
350+
}
351+
}
347352
}
348353

349354
fn identity() -> Self {

k256/src/arithmetic/affine.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use elliptic_curve::{
99
Error, Result,
1010
group::{GroupEncoding, prime::PrimeCurveAffine},
1111
point::{AffineCoordinates, DecompactPoint, DecompressPoint, NonIdentity},
12+
rand_core::TryRngCore,
1213
sec1::{self, FromEncodedPoint, ToEncodedPoint},
1314
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
1415
zeroize::DefaultIsZeroes,
@@ -73,6 +74,22 @@ impl AffinePoint {
7374
]),
7475
infinity: 0,
7576
};
77+
78+
/// Generate a random [`AffinePoint`].
79+
pub fn try_from_rng<R: TryRngCore + ?Sized>(
80+
rng: &mut R,
81+
) -> core::result::Result<Self, R::Error> {
82+
let mut bytes = FieldBytes::default();
83+
let mut sign = 0;
84+
85+
loop {
86+
rng.try_fill_bytes(&mut bytes)?;
87+
rng.try_fill_bytes(core::array::from_mut(&mut sign))?;
88+
if let Some(point) = Self::decompress(&bytes, Choice::from(sign & 1)).into_option() {
89+
return Ok(point);
90+
}
91+
}
92+
}
7693
}
7794

7895
impl AffinePoint {

k256/src/arithmetic/projective.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use elliptic_curve::{
1212
BatchNormalize, CurveGroup, Error, Result,
1313
group::{
1414
Group, GroupEncoding,
15-
ff::Field,
1615
prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup},
1716
},
1817
rand_core::TryRngCore,
@@ -411,7 +410,7 @@ impl Group for ProjectivePoint {
411410
type Scalar = Scalar;
412411

413412
fn try_from_rng<R: TryRngCore + ?Sized>(rng: &mut R) -> core::result::Result<Self, R::Error> {
414-
Ok(Self::GENERATOR * Scalar::try_from_rng(rng)?)
413+
AffinePoint::try_from_rng(rng).map(Self::from)
415414
}
416415

417416
fn identity() -> Self {

primeorder/src/affine.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use elliptic_curve::{
1313
ff::{Field, PrimeField},
1414
group::{GroupEncoding, prime::PrimeCurveAffine},
1515
point::{AffineCoordinates, DecompactPoint, DecompressPoint, Double, NonIdentity},
16+
rand_core::TryRngCore,
1617
sec1::{
1718
self, CompressedPoint, EncodedPoint, FromEncodedPoint, ModulusSize, ToCompactEncodedPoint,
1819
ToEncodedPoint, UncompressedPointSize,
@@ -77,6 +78,28 @@ where
7778
}
7879
}
7980

81+
impl<C> AffinePoint<C>
82+
where
83+
C: PrimeCurveParams,
84+
FieldBytes<C>: Copy,
85+
{
86+
/// Generate a cryptographically random [`AffinePoint`].
87+
pub fn try_from_rng<R: TryRngCore + ?Sized>(
88+
rng: &mut R,
89+
) -> core::result::Result<Self, R::Error> {
90+
let mut bytes = FieldBytes::<C>::default();
91+
let mut sign = 0;
92+
93+
loop {
94+
rng.try_fill_bytes(&mut bytes)?;
95+
rng.try_fill_bytes(core::array::from_mut(&mut sign))?;
96+
if let Some(point) = Self::decompress(&bytes, Choice::from(sign & 1)).into_option() {
97+
return Ok(point);
98+
}
99+
}
100+
}
101+
}
102+
80103
impl<C> AffineCoordinates for AffinePoint<C>
81104
where
82105
C: PrimeCurveParams,

primeorder/src/projective.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,13 @@ where
258258

259259
impl<C> Group for ProjectivePoint<C>
260260
where
261-
Self: Double,
262261
C: PrimeCurveParams,
262+
FieldBytes<C>: Copy,
263263
{
264264
type Scalar = Scalar<C>;
265265

266266
fn try_from_rng<R: TryRngCore + ?Sized>(rng: &mut R) -> core::result::Result<Self, R::Error> {
267-
Ok(Self::GENERATOR * <Scalar<C> as Field>::try_from_rng(rng)?)
267+
AffinePoint::try_from_rng(rng).map(Self::from)
268268
}
269269

270270
fn identity() -> Self {
@@ -311,8 +311,8 @@ where
311311

312312
impl<C> CurveGroup for ProjectivePoint<C>
313313
where
314-
Self: Double,
315314
C: PrimeCurveParams,
315+
FieldBytes<C>: Copy,
316316
{
317317
type AffineRepr = AffinePoint<C>;
318318

@@ -331,8 +331,8 @@ where
331331

332332
impl<const N: usize, C> BatchNormalize<[ProjectivePoint<C>; N]> for ProjectivePoint<C>
333333
where
334-
Self: Double,
335334
C: PrimeCurveParams,
335+
FieldBytes<C>: Copy,
336336
{
337337
type Output = [<Self as CurveGroup>::AffineRepr; N];
338338

@@ -348,8 +348,8 @@ where
348348
#[cfg(feature = "alloc")]
349349
impl<C> BatchNormalize<[ProjectivePoint<C>]> for ProjectivePoint<C>
350350
where
351-
Self: Double,
352351
C: PrimeCurveParams,
352+
FieldBytes<C>: Copy,
353353
{
354354
type Output = Vec<<Self as CurveGroup>::AffineRepr>;
355355

@@ -400,16 +400,16 @@ where
400400

401401
impl<C> LinearCombination<[(Self, Scalar<C>)]> for ProjectivePoint<C>
402402
where
403-
Self: Double,
404403
C: PrimeCurveParams,
404+
FieldBytes<C>: Copy,
405405
{
406406
// TODO(tarcieri): optimized implementation
407407
}
408408

409409
impl<C, const N: usize> LinearCombination<[(Self, Scalar<C>); N]> for ProjectivePoint<C>
410410
where
411-
Self: Double,
412411
C: PrimeCurveParams,
412+
FieldBytes<C>: Copy,
413413
{
414414
// TODO(tarcieri): optimized implementation
415415
}

0 commit comments

Comments
 (0)