Skip to content

Commit 7ed415c

Browse files
daxpeddatarcieri
andcommitted
Use rejection sampling for random point generation
Co-Authored-By: Tony Arcieri <[email protected]>
1 parent 912d939 commit 7ed415c

File tree

4 files changed

+49
-17
lines changed

4 files changed

+49
-17
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/projective.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![allow(clippy::op_ref)]
44

55
use super::{AffinePoint, CURVE_EQUATION_B_SINGLE, FieldElement, Scalar};
6-
use crate::{CompressedPoint, EncodedPoint, PublicKey, Secp256k1};
6+
use crate::{CompressedPoint, EncodedPoint, FieldBytes, PublicKey, Secp256k1};
77
use core::{
88
iter::Sum,
99
ops::{Add, AddAssign, Neg, Sub, SubAssign},
@@ -12,9 +12,9 @@ use elliptic_curve::{
1212
BatchNormalize, CurveGroup, Error, Result,
1313
group::{
1414
Group, GroupEncoding,
15-
ff::Field,
1615
prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup},
1716
},
17+
point::DecompressPoint,
1818
rand_core::TryRngCore,
1919
sec1::{FromEncodedPoint, ToEncodedPoint},
2020
subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption},
@@ -411,7 +411,18 @@ impl Group for ProjectivePoint {
411411
type Scalar = Scalar;
412412

413413
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)?)
414+
let mut bytes = FieldBytes::default();
415+
let mut sign = 0;
416+
417+
loop {
418+
rng.try_fill_bytes(&mut bytes)?;
419+
rng.try_fill_bytes(core::array::from_mut(&mut sign))?;
420+
if let Some(point) =
421+
AffinePoint::decompress(&bytes, Choice::from(sign & 1)).into_option()
422+
{
423+
return Ok(point.into());
424+
}
425+
}
415426
}
416427

417428
fn identity() -> Self {

primeorder/src/projective.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use elliptic_curve::{
1818
prime::{PrimeCurve, PrimeGroup},
1919
},
2020
ops::{BatchInvert, LinearCombination},
21-
point::{Double, NonIdentity},
21+
point::{DecompressPoint, Double, NonIdentity},
2222
rand_core::TryRngCore,
2323
sec1::{
2424
CompressedPoint, EncodedPoint, FromEncodedPoint, ModulusSize, ToEncodedPoint,
@@ -258,13 +258,24 @@ 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+
let mut bytes = FieldBytes::<C>::default();
268+
let mut sign = 0;
269+
270+
loop {
271+
rng.try_fill_bytes(&mut bytes)?;
272+
rng.try_fill_bytes(core::array::from_mut(&mut sign))?;
273+
if let Some(point) =
274+
AffinePoint::decompress(&bytes, Choice::from(sign & 1)).into_option()
275+
{
276+
return Ok(point.into());
277+
}
278+
}
268279
}
269280

270281
fn identity() -> Self {
@@ -311,8 +322,8 @@ where
311322

312323
impl<C> CurveGroup for ProjectivePoint<C>
313324
where
314-
Self: Double,
315325
C: PrimeCurveParams,
326+
FieldBytes<C>: Copy,
316327
{
317328
type AffineRepr = AffinePoint<C>;
318329

@@ -331,8 +342,8 @@ where
331342

332343
impl<const N: usize, C> BatchNormalize<[ProjectivePoint<C>; N]> for ProjectivePoint<C>
333344
where
334-
Self: Double,
335345
C: PrimeCurveParams,
346+
FieldBytes<C>: Copy,
336347
{
337348
type Output = [<Self as CurveGroup>::AffineRepr; N];
338349

@@ -348,8 +359,8 @@ where
348359
#[cfg(feature = "alloc")]
349360
impl<C> BatchNormalize<[ProjectivePoint<C>]> for ProjectivePoint<C>
350361
where
351-
Self: Double,
352362
C: PrimeCurveParams,
363+
FieldBytes<C>: Copy,
353364
{
354365
type Output = Vec<<Self as CurveGroup>::AffineRepr>;
355366

@@ -400,16 +411,16 @@ where
400411

401412
impl<C> LinearCombination<[(Self, Scalar<C>)]> for ProjectivePoint<C>
402413
where
403-
Self: Double,
404414
C: PrimeCurveParams,
415+
FieldBytes<C>: Copy,
405416
{
406417
// TODO(tarcieri): optimized implementation
407418
}
408419

409420
impl<C, const N: usize> LinearCombination<[(Self, Scalar<C>); N]> for ProjectivePoint<C>
410421
where
411-
Self: Double,
412422
C: PrimeCurveParams,
423+
FieldBytes<C>: Copy,
413424
{
414425
// TODO(tarcieri): optimized implementation
415426
}

0 commit comments

Comments
 (0)