Rewrite CompressedEdwardsY::decompress() to use FieldElement::sqrt_ratio

This commit is contained in:
Henry de Valence 2017-02-22 20:51:44 -08:00
parent 1febf3f753
commit d450659b7f
2 changed files with 20 additions and 41 deletions

View file

@ -127,45 +127,24 @@ impl CompressedEdwardsY {
/// Attempt to decompress to an `ExtendedPoint`.
///
/// # Warning
///
/// This function will fail and return None if both vx²-u=0 and vx²+u=0.
/// Returns `None` if the input is not the `y`-coordinate of a
/// curve point.
pub fn decompress(&self) -> Option<ExtendedPoint> { // FromBytes()
let mut u: FieldElement;
let mut v: FieldElement;
let v3: FieldElement;
let vxx: FieldElement;
let Y = FieldElement::from_bytes(&self.0);
let Z = FieldElement::one();
let YY = Y.square();
let u = &YY - &Z; // u = y²-1
let v = &(&YY * &constants::d) + &Z; // v = dy²+1
let (is_nonzero_square, mut X) = FieldElement::sqrt_ratio(&u, &v);
let mut X: FieldElement;
let Y: FieldElement;
let Z: FieldElement;
let T: FieldElement;
if is_nonzero_square != 1u8 { return None; }
Y = FieldElement::from_bytes(&self.0);
Z = FieldElement::one();
// Flip the sign of X if it's not correct
let compressed_sign_bit = self[31] >> 7;
let current_sign_bit = X.is_negative_ed25519();
X.conditional_negate(current_sign_bit ^ compressed_sign_bit);
u = Y.square();
v = &u * &constants::d;
u -= &Z; // u = y²-1
v += &Z; // v = dy²+1
v3 = &v.square() * &v; // v3 = v³
X = (&v3.square() * &(&v * &u)).pow_p58(); // x = (uv⁷)^((q-5)/8)
X *= &(&u * &v3); // x = (uv³)(uv⁷)^((q-5)/8)
vxx = &v * &X.square();
if (&vxx - &u).is_nonzero() == 1 { // vx²-u
if (&vxx + &u).is_nonzero() == 1 { // vx²+u
return None;
}
X *= &constants::SQRT_M1;
}
if X.is_negative_ed25519() != (self[31] >> 7) as i32 {
X = X.neg();
}
T = &X * &Y;
Some(ExtendedPoint{ X: X, Y: Y, Z: Z, T: T })
Some(ExtendedPoint{ X: X, Y: Y, Z: Z, T: &X * &Y })
}
}

View file

@ -517,16 +517,16 @@ impl FieldElement {
(!equal_so_far & 1 & greater) as u8
}
/// Determine if this `FieldElement` is negative, in the
/// sense used in the ed25519 paper.
/// Determine if this `FieldElement` is negative, in the sense
/// used in the ed25519 paper: `x` is negative if the low bit is
/// set.
///
/// # Return
///
/// If negative, return `1i32`. Otherwise, return `0i32`.
// XXX should return u8
pub fn is_negative_ed25519(&self) -> i32 { //FeIsNegative
/// If negative, return `1u8`. Otherwise, return `0u8`.
pub fn is_negative_ed25519(&self) -> u8 { //FeIsNegative
let bytes = self.to_bytes();
(bytes[0] & 1) as i32
(bytes[0] & 1) as u8
}
/// Determine if this `FieldElement` is negative, in the