Skip to content

Commit fed493a

Browse files
authored
elliptic-curve: RNG followups (#2208)
- Impls the `Generate` trait for `NonIdentity`, deprecates `NonIdentity::random` - Impls a `Generate`-like API for `BlindedScalar` (it can't use the `Generate` trait because it needs the scalar to blind in addition to an RNG) - Note: above changes `BlindedScalar::new` not to have an RNG argument and implicitly using `getrandom::SysRng`, and the old function is preserved as `BlindedSclar::new_with_rng`
1 parent 02e91f5 commit fed493a

2 files changed

Lines changed: 62 additions & 25 deletions

File tree

elliptic-curve/src/point/non_identity.rs

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
33
#![cfg(feature = "arithmetic")]
44

5+
use common::Generate;
56
use core::ops::{Deref, Mul};
6-
77
use group::{Group, GroupEncoding, prime::PrimeCurveAffine};
8-
use rand_core::{CryptoRng, TryCryptoRng, TryRngCore};
8+
use rand_core::{CryptoRng, TryCryptoRng};
99
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
1010

1111
#[cfg(feature = "alloc")]
1212
use alloc::vec::Vec;
13-
1413
#[cfg(feature = "serde")]
1514
use serdect::serde::{Deserialize, Serialize, de, ser};
1615
use zeroize::Zeroize;
@@ -56,7 +55,7 @@ where
5655
impl<P> NonIdentity<P> {
5756
/// Transform array reference containing [`NonIdentity`] points to an array reference to the
5857
/// inner point type.
59-
pub fn cast_array_as_inner<const N: usize>(points: &[Self; N]) -> &[P; N] {
58+
pub fn array_as_inner<const N: usize>(points: &[Self; N]) -> &[P; N] {
6059
// SAFETY: `NonIdentity` is a `repr(transparent)` newtype for `P` so it's safe to cast to
6160
// the inner `P` type.
6261
#[allow(unsafe_code)]
@@ -66,14 +65,27 @@ impl<P> NonIdentity<P> {
6665
}
6766

6867
/// Transform slice containing [`NonIdentity`] points to a slice of the inner point type.
69-
pub fn cast_slice_as_inner(points: &[Self]) -> &[P] {
68+
pub fn slice_as_inner(points: &[Self]) -> &[P] {
7069
// SAFETY: `NonIdentity` is a `repr(transparent)` newtype for `P` so it's safe to cast to
7170
// the inner `P` type.
7271
#[allow(unsafe_code)]
7372
unsafe {
7473
&*(points as *const [NonIdentity<P>] as *const [P])
7574
}
7675
}
76+
77+
/// Transform array reference containing [`NonIdentity`] points to an array reference to the
78+
/// inner point type.
79+
#[deprecated(since = "0.14.0", note = "use `NonIdentity::array_as_inner` instead")]
80+
pub fn cast_array_as_inner<const N: usize>(points: &[Self; N]) -> &[P; N] {
81+
Self::array_as_inner(points)
82+
}
83+
84+
/// Transform slice containing [`NonIdentity`] points to a slice of the inner point type.
85+
#[deprecated(since = "0.14.0", note = "use `NonIdentity::slice_as_inner` instead")]
86+
pub fn cast_slice_as_inner(points: &[Self]) -> &[P] {
87+
Self::slice_as_inner(points)
88+
}
7789
}
7890

7991
impl<P: Copy> NonIdentity<P> {
@@ -88,6 +100,7 @@ where
88100
P: ConditionallySelectable + ConstantTimeEq + CurveGroup + Default,
89101
{
90102
/// Generate a random `NonIdentity<ProjectivePoint>`.
103+
#[deprecated(since = "0.14.0", note = "use the `Generate` trait instead")]
91104
pub fn random<R: CryptoRng + ?Sized>(rng: &mut R) -> Self {
92105
loop {
93106
if let Some(point) = Self::new(P::random(rng)).into() {
@@ -96,17 +109,6 @@ where
96109
}
97110
}
98111

99-
/// Generate a random `NonIdentity<ProjectivePoint>`.
100-
pub fn try_from_rng<R: TryCryptoRng + TryRngCore + ?Sized>(
101-
rng: &mut R,
102-
) -> Result<Self, R::Error> {
103-
loop {
104-
if let Some(point) = Self::new(P::try_from_rng(rng)?).into() {
105-
break Ok(point);
106-
}
107-
}
108-
}
109-
110112
/// Converts this element into its affine representation.
111113
pub fn to_affine(self) -> NonIdentity<P::AffineRepr> {
112114
NonIdentity {
@@ -150,7 +152,7 @@ where
150152
type Output = [NonIdentity<P::AffineRepr>; N];
151153

152154
fn batch_normalize(points: &[Self; N]) -> [NonIdentity<P::AffineRepr>; N] {
153-
let points = Self::cast_array_as_inner::<N>(points);
155+
let points = Self::array_as_inner::<N>(points);
154156
let affine_points = <P as BatchNormalize<_>>::batch_normalize(points);
155157
affine_points.map(|point| NonIdentity { point })
156158
}
@@ -164,7 +166,7 @@ where
164166
type Output = Vec<NonIdentity<P::AffineRepr>>;
165167

166168
fn batch_normalize(points: &[Self]) -> Vec<NonIdentity<P::AffineRepr>> {
167-
let points = Self::cast_slice_as_inner(points);
169+
let points = Self::slice_as_inner(points);
168170
let affine_points = <P as BatchNormalize<_>>::batch_normalize(points);
169171
affine_points
170172
.into_iter()
@@ -201,6 +203,19 @@ impl<P> Deref for NonIdentity<P> {
201203
}
202204
}
203205

206+
impl<P> Generate for NonIdentity<P>
207+
where
208+
P: ConditionallySelectable + ConstantTimeEq + Default + Generate,
209+
{
210+
fn try_generate_from_rng<R: TryCryptoRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
211+
loop {
212+
if let Some(point) = Self::new(P::try_generate_from_rng(rng)?).into() {
213+
break Ok(point);
214+
}
215+
}
216+
}
217+
}
218+
204219
impl<P> GroupEncoding for NonIdentity<P>
205220
where
206221
P: ConditionallySelectable + ConstantTimeEq + Default + GroupEncoding,

elliptic-curve/src/scalar/blinded.rs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
33
use super::Scalar;
44
use crate::{CurveArithmetic, ops::Invert};
5+
use common::Generate;
56
use core::fmt;
6-
use group::ff::Field;
7-
use rand_core::CryptoRng;
7+
use rand_core::{CryptoRng, TryCryptoRng};
88
use subtle::CtOption;
99
use zeroize::Zeroize;
1010

11+
#[cfg(feature = "getrandom")]
12+
use common::getrandom::{self, SysRng};
13+
1114
/// Scalar blinded with a randomly generated masking value.
1215
///
1316
/// This provides a randomly blinded impl of [`Invert`] which is useful for
@@ -37,12 +40,31 @@ impl<C> BlindedScalar<C>
3740
where
3841
C: CurveArithmetic,
3942
{
43+
/// Create a new [`BlindedScalar`] using the system's ambient secure RNG.
44+
#[cfg(feature = "getrandom")]
45+
pub fn new(scalar: Scalar<C>) -> Self {
46+
Self::try_new(scalar).expect("RNG error")
47+
}
48+
49+
/// Create a new [`BlindedScalar`] using the system's ambient secure RNG.
50+
#[cfg(feature = "getrandom")]
51+
pub fn try_new(scalar: Scalar<C>) -> Result<Self, getrandom::Error> {
52+
Self::try_new_from_rng(scalar, &mut SysRng)
53+
}
54+
55+
/// Create a new [`BlindedScalar`] from a scalar and a [`CryptoRng`].
56+
pub fn new_from_rng<R: CryptoRng + ?Sized>(scalar: Scalar<C>, rng: &mut R) -> Self {
57+
let Ok(ret) = Self::try_new_from_rng(scalar, rng);
58+
ret
59+
}
60+
4061
/// Create a new [`BlindedScalar`] from a scalar and a [`CryptoRng`].
41-
pub fn new<R: CryptoRng + ?Sized>(scalar: Scalar<C>, rng: &mut R) -> Self {
42-
Self {
43-
scalar,
44-
mask: Scalar::<C>::random(rng),
45-
}
62+
pub fn try_new_from_rng<R>(scalar: Scalar<C>, rng: &mut R) -> Result<Self, R::Error>
63+
where
64+
R: TryCryptoRng + ?Sized,
65+
{
66+
let mask = Scalar::<C>::try_generate_from_rng(rng)?;
67+
Ok(Self { scalar, mask })
4668
}
4769
}
4870

0 commit comments

Comments
 (0)