mirror of
https://github.com/saymrwulf/curve25519-dalek-source.git
synced 2026-09-06 20:41:14 +00:00
Properly handle exceptional points.
This commit is contained in:
parent
19d452c2dc
commit
db53b58e89
1 changed files with 34 additions and 7 deletions
41
src/curve.rs
41
src/curve.rs
|
|
@ -189,6 +189,18 @@ impl CompressedMontgomeryU {
|
||||||
// y = (u - 1) / (u + 1)
|
// y = (u - 1) / (u + 1)
|
||||||
|
|
||||||
let u = FieldElement::from_bytes(&self.0);
|
let u = FieldElement::from_bytes(&self.0);
|
||||||
|
|
||||||
|
// If u = -1, then v^2 = u*(u^2+486662*u+1) = 486660.
|
||||||
|
// But 486660 is nonsquare mod p, so this is not a curve point.
|
||||||
|
//
|
||||||
|
// XXX what does Signal do here?
|
||||||
|
//
|
||||||
|
// Note: currently, without this check, u = -1 will accidentally
|
||||||
|
// decode to a valid (but incorrect) point, since 0.invert() = 0.
|
||||||
|
if u == FieldElement::minus_one() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let u_plus_1_inv = (&u + &FieldElement::one()).invert();
|
let u_plus_1_inv = (&u + &FieldElement::one()).invert();
|
||||||
let y = &(&u - &FieldElement::one()) * &u_plus_1_inv;
|
let y = &(&u - &FieldElement::one()) * &u_plus_1_inv;
|
||||||
|
|
||||||
|
|
@ -430,9 +442,11 @@ impl ProjectivePoint {
|
||||||
/// Convert this point to a `CompressedMontgomeryU`.
|
/// Convert this point to a `CompressedMontgomeryU`.
|
||||||
/// Note that this discards the sign.
|
/// Note that this discards the sign.
|
||||||
///
|
///
|
||||||
/// XXX check for div by zero: when is Z = Y ?
|
/// # Return
|
||||||
/// XXX exceptional points for the birational map
|
/// - `None` if `self` is the identity point;
|
||||||
pub fn compress_montgomery(&self) -> CompressedMontgomeryU {
|
/// - `Some(CompressedMontgomeryU)` otherwise.
|
||||||
|
///
|
||||||
|
pub fn compress_montgomery(&self) -> Option<CompressedMontgomeryU> {
|
||||||
// u = (1 + y) / (1 - y)
|
// u = (1 + y) / (1 - y)
|
||||||
// v = sqrt(-486664) * u / x
|
// v = sqrt(-486664) * u / x
|
||||||
//
|
//
|
||||||
|
|
@ -440,11 +454,18 @@ impl ProjectivePoint {
|
||||||
//
|
//
|
||||||
// u = (1 + Y/Z) / (1 - Y/Z);
|
// u = (1 + Y/Z) / (1 - Y/Z);
|
||||||
// = (Z + Y) / (Z - Y);
|
// = (Z + Y) / (Z - Y);
|
||||||
|
//
|
||||||
|
// exceptional points:
|
||||||
|
// y = 1 <=> Y/Z = 1 <=> Z - Y = 0
|
||||||
let Z_plus_Y = &self.Z + &self.Y;
|
let Z_plus_Y = &self.Z + &self.Y;
|
||||||
let Z_minus_Y = &self.Z - &self.Y;
|
let Z_minus_Y = &self.Z - &self.Y;
|
||||||
let u = &Z_plus_Y * &Z_minus_Y.invert();
|
let u = &Z_plus_Y * &Z_minus_Y.invert();
|
||||||
|
|
||||||
CompressedMontgomeryU(u.to_bytes())
|
if Z_minus_Y.is_zero() == 0u8 {
|
||||||
|
CompressedMontgomeryU(u.to_bytes())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1072,14 +1093,20 @@ mod test {
|
||||||
///
|
///
|
||||||
/// XXX what does Signal do here?
|
/// XXX what does Signal do here?
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
|
||||||
fn test_u_minus_one_monty() {
|
fn test_u_minus_one_monty() {
|
||||||
let mut m1 = FieldElement::zero();
|
let mut m1 = FieldElement::zero();
|
||||||
m1[0] = -1;
|
m1[0] = -1;
|
||||||
let m1_bytes = m1.to_bytes();
|
let m1_bytes = m1.to_bytes();
|
||||||
let div_by_zero_u = CompressedMontgomeryU(m1_bytes);
|
let div_by_zero_u = CompressedMontgomeryU(m1_bytes);
|
||||||
let p = div_by_zero_u.decompress().unwrap();
|
assert!(div_by_zero_u.decompress().is_none());
|
||||||
println!("{:?}", p);
|
}
|
||||||
|
|
||||||
|
/// Montgomery compression of the identity point should
|
||||||
|
/// fail (it's sent to infinity).
|
||||||
|
#[test]
|
||||||
|
fn test_identity_to_monty() {
|
||||||
|
let id = ExtendedPoint::identity();
|
||||||
|
assert!(id.compressed_montgomery().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test round-trip decompression for the basepoint.
|
/// Test round-trip decompression for the basepoint.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue