From 4678a67ce6198e3289e9c2d8854a79b516bac59e Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Sun, 11 Aug 2019 12:35:25 -0600 Subject: [PATCH] Add implementation of point doubling. --- benches/groups.rs | 6 ++++ src/g1.rs | 69 ++++++++++++++++++++++++++++++++++++ src/g2.rs | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) diff --git a/benches/groups.rs b/benches/groups.rs index 13922f993..ddd06d478 100644 --- a/benches/groups.rs +++ b/benches/groups.rs @@ -32,6 +32,9 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function(&format!("{} to affine", name), move |b| { b.iter(|| G1Affine::from(black_box(a))) }); + c.bench_function(&format!("{} doubling", name), move |b| { + b.iter(|| black_box(a).double()) + }); } // G2Affine @@ -59,6 +62,9 @@ fn criterion_benchmark(c: &mut Criterion) { c.bench_function(&format!("{} to affine", name), move |b| { b.iter(|| G2Affine::from(black_box(a))) }); + c.bench_function(&format!("{} doubling", name), move |b| { + b.iter(|| black_box(a).double()) + }); } } diff --git a/src/g1.rs b/src/g1.rs index 1aca849ff..0cdbd7b06 100644 --- a/src/g1.rs +++ b/src/g1.rs @@ -226,6 +226,38 @@ impl G1Projective { } } + /// Computes the doubling of this point. + pub fn double(&self) -> G1Projective { + // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + // + // There are no points of order 2. + + let a = self.x.square(); + let b = self.y.square(); + let c = b.square(); + let d = self.x + b; + let d = d.square(); + let d = d - a - c; + let d = d + d; + let e = a + a + a; + let f = e.square(); + let z3 = self.z * self.y; + let z3 = z3 + z3; + let x3 = f - (d + d); + let c = c + c; + let c = c + c; + let c = c + c; + let y3 = e * (d - x3) - c; + + let tmp = G1Projective { + x: x3, + y: y3, + z: z3, + }; + + G1Projective::conditional_select(&tmp, &G1Projective::identity(), self.is_identity()) + } + /// Returns true if this element is the identity (the point at infinity). #[inline] pub fn is_identity(&self) -> Choice { @@ -392,3 +424,40 @@ fn test_affine_to_projective() { assert!(bool::from(G1Projective::from(b).is_on_curve())); assert!(bool::from(G1Projective::from(b).is_identity())); } + +#[test] +fn test_doubling() { + { + let tmp = G1Projective::identity().double(); + assert!(bool::from(tmp.is_identity())); + assert!(bool::from(tmp.is_on_curve())); + } + { + let tmp = G1Projective::generator().double(); + assert!(!bool::from(tmp.is_identity())); + assert!(bool::from(tmp.is_on_curve())); + + assert_eq!( + G1Affine::from(tmp), + G1Affine { + x: Fp::from_raw_unchecked([ + 0x53e978ce58a9ba3c, + 0x3ea0583c4f3d65f9, + 0x4d20bb47f0012960, + 0xa54c664ae5b2b5d9, + 0x26b552a39d7eb21f, + 0x8895d26e68785 + ]), + y: Fp::from_raw_unchecked([ + 0x70110b3298293940, + 0xda33c5393f1f6afc, + 0xb86edfd16a5aa785, + 0xaec6d1c9e7b1c895, + 0x25cfc2b522d11720, + 0x6361c83f8d09b15 + ]), + infinity: Choice::from(0u8) + } + ); + } +} diff --git a/src/g2.rs b/src/g2.rs index 024f6ebe3..a8d925b80 100644 --- a/src/g2.rs +++ b/src/g2.rs @@ -277,6 +277,38 @@ impl G2Projective { } } + /// Computes the doubling of this point. + pub fn double(&self) -> G2Projective { + // http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l + // + // There are no points of order 2. + + let a = self.x.square(); + let b = self.y.square(); + let c = b.square(); + let d = self.x + b; + let d = d.square(); + let d = d - a - c; + let d = d + d; + let e = a + a + a; + let f = e.square(); + let z3 = self.z * self.y; + let z3 = z3 + z3; + let x3 = f - (d + d); + let c = c + c; + let c = c + c; + let c = c + c; + let y3 = e * (d - x3) - c; + + let tmp = G2Projective { + x: x3, + y: y3, + z: z3, + }; + + G2Projective::conditional_select(&tmp, &G2Projective::identity(), self.is_identity()) + } + /// Returns true if this element is the identity (the point at infinity). #[inline] pub fn is_identity(&self) -> Choice { @@ -473,3 +505,60 @@ fn test_affine_to_projective() { assert!(bool::from(G2Projective::from(b).is_on_curve())); assert!(bool::from(G2Projective::from(b).is_identity())); } + +#[test] +fn test_doubling() { + { + let tmp = G2Projective::identity().double(); + assert!(bool::from(tmp.is_identity())); + assert!(bool::from(tmp.is_on_curve())); + } + { + let tmp = G2Projective::generator().double(); + assert!(!bool::from(tmp.is_identity())); + assert!(bool::from(tmp.is_on_curve())); + + assert_eq!( + G2Affine::from(tmp), + G2Affine { + x: Fp2 { + c0: Fp::from_raw_unchecked([ + 0xe9d9e2da9620f98b, + 0x54f1199346b97f36, + 0x3db3b820376bed27, + 0xcfdb31c9b0b64f4c, + 0x41d7c12786354493, + 0x5710794c255c064 + ]), + c1: Fp::from_raw_unchecked([ + 0xd6c1d3ca6ea0d06e, + 0xda0cbd905595489f, + 0x4f5352d43479221d, + 0x8ade5d736f8c97e0, + 0x48cc8433925ef70e, + 0x8d7ea71ea91ef81 + ]), + }, + y: Fp2 { + c0: Fp::from_raw_unchecked([ + 0x15ba26eb4b0d186f, + 0xd086d64b7e9e01e, + 0xc8b848dd652f4c78, + 0xeecf46a6123bae4f, + 0x255e8dd8b6dc812a, + 0x164142af21dcf93f + ]), + c1: Fp::from_raw_unchecked([ + 0xf9b4a1a895984db4, + 0xd417b114cccff748, + 0x6856301fc89f086e, + 0x41c777878931e3da, + 0x3556b155066a2105, + 0xacf7d325cb89cf + ]), + }, + infinity: Choice::from(0u8) + } + ); + } +}