Fix Group::random implementation for Pallas and Vesta

Also removes the broken CurveAffine::from_bytes_wide and unused
CurveAffine::to_bytes_wide methods.
This commit is contained in:
Jack Grigg 2021-03-02 21:29:59 +00:00
parent 8122ef3d5d
commit 62e50ae6bd
2 changed files with 21 additions and 53 deletions

View file

@ -125,14 +125,6 @@ pub trait CurveAffine:
writer.write_all(compressed.as_ref())
}
/// Attempts to obtain a group element from its uncompressed 64-byte little
/// endian representation.
fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption<Self>;
/// Obtains the uncompressed, 64-byte little endian representation of this
/// element.
fn to_bytes_wide(&self) -> [u8; 64];
/// Returns the curve constant $a$.
fn a() -> Self::Base;

View file

@ -62,13 +62,27 @@ macro_rules! new_curve_impl {
fn random(mut rng: impl RngCore) -> Self {
loop {
let mut buf = [0; 64];
rng.fill_bytes(&mut buf);
let p: Option<$name_affine> = $name_affine::from_bytes_wide(&buf).into();
if let Some(p) = p {
if !bool::from(p.is_identity()) {
break p.to_curve();
}
let x = $base::random(&mut rng);
let ysign = (rng.next_u32() % 2) as u8;
if x.is_zero() && ysign == 0 {
// This would be the identity if encoded, and Group::random must
// sample from the non-identity elements of the group.
continue;
}
let x3 = x.square() * x;
let y = (x3 + $name::curve_constant_b()).sqrt();
if let Some(y) = Option::<$base>::from(y) {
let sign = y.to_bytes()[0] & 1;
let y = if ysign ^ sign == 0 { y } else { -y };
let p = $name_affine {
x,
y,
infinity: Choice::from(0u8),
};
break p.to_curve();
}
}
}
@ -654,44 +668,6 @@ macro_rules! new_curve_impl {
CtOption::new(p, p.is_on_curve())
}
fn from_bytes_wide(bytes: &[u8; 64]) -> CtOption<Self> {
let mut xbytes = [0u8; 32];
let mut ybytes = [0u8; 32];
xbytes.copy_from_slice(&bytes[0..32]);
ybytes.copy_from_slice(&bytes[32..64]);
$base::from_bytes(&xbytes).and_then(|x| {
$base::from_bytes(&ybytes).and_then(|y| {
CtOption::new(Self::identity(), x.ct_is_zero() & y.ct_is_zero()).or_else(|| {
let on_curve =
(x * x.square() + $name::curve_constant_b()).ct_eq(&y.square());
CtOption::new(
$name_affine {
x,
y,
infinity: Choice::from(0u8),
},
Choice::from(on_curve),
)
})
})
})
}
fn to_bytes_wide(&self) -> [u8; 64] {
// TODO: not constant time
if bool::from(self.is_identity()) {
[0; 64]
} else {
let mut out = [0u8; 64];
(&mut out[0..32]).copy_from_slice(&self.x.to_bytes());
(&mut out[32..64]).copy_from_slice(&self.y.to_bytes());
out
}
}
fn a() -> Self::Base {
$name::curve_constant_a()
}