From 03f3505abf93a962f91c110fba7d5ebda33e4759 Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Sun, 12 Feb 2023 21:55:06 +0100 Subject: [PATCH 1/3] Fix Elligator benchmark and add one for Elligator inverse --- benches/dalek_benchmarks.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/benches/dalek_benchmarks.rs b/benches/dalek_benchmarks.rs index d60eb6cb..1db1c645 100644 --- a/benches/dalek_benchmarks.rs +++ b/benches/dalek_benchmarks.rs @@ -273,6 +273,13 @@ mod ristretto_benches { }); } + fn elligator_inv(c: &mut Criterion) { + c.bench_function("RistrettoPoint Elligator Inverse", |b| { + let B = &constants::RISTRETTO_BASEPOINT_POINT; + b.iter(|| B.elligator_ristretto_flavor_inverse()); + }); + } + fn double_and_compress_batch(c: &mut BenchmarkGroup) { for batch_size in &BATCH_SIZES { c.bench_with_input( @@ -303,6 +310,14 @@ mod ristretto_benches { decompress, double_and_compress_group, } + + criterion_group! { + name = elligator_benches; + config = Criterion::default(); + targets = + elligator, + elligator_inv, + } } mod montgomery_benches { @@ -367,6 +382,7 @@ mod scalar_benches { } criterion_main!( + ristretto_benches::elligator_benches, scalar_benches::scalar_benches, montgomery_benches::montgomery_benches, ristretto_benches::ristretto_benches, From 2009d1da98fa7ba83286689fcb45622ed54c8b4e Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Sun, 12 Feb 2023 21:55:54 +0100 Subject: [PATCH 2/3] lizard: Remove stage2_build feature gate so that tests run --- src/lizard/lizard_constants.rs | 2 +- src/lizard/lizard_ristretto.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lizard/lizard_constants.rs b/src/lizard/lizard_constants.rs index beb8882b..bcd463aa 100644 --- a/src/lizard/lizard_constants.rs +++ b/src/lizard/lizard_constants.rs @@ -13,7 +13,7 @@ pub(crate) use lizard::u32_constants::*; // Tests // ------------------------------------------------------------------------ -#[cfg(all(test, feature = "stage2_build"))] +#[cfg(all(test))] mod test { use super::*; diff --git a/src/lizard/lizard_ristretto.rs b/src/lizard/lizard_ristretto.rs index 31ee528b..04fbe0c1 100644 --- a/src/lizard/lizard_ristretto.rs +++ b/src/lizard/lizard_ristretto.rs @@ -229,7 +229,7 @@ impl RistrettoPoint { // Tests // ------------------------------------------------------------------------ -#[cfg(all(test, feature = "stage2_build"))] +#[cfg(all(test))] mod test { extern crate sha2; From 66cbe7eaddd6fc4b92bd2e4a00619de91f1e5e7c Mon Sep 17 00:00:00 2001 From: Bas Westerbaan Date: Sun, 12 Feb 2023 21:56:30 +0100 Subject: [PATCH 3/3] Elligator: return distinct elements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Does not impact performance: RistrettoPoint Elligator Inverse time: [27.236 µs 27.247 µs 27.259 µs] change: [-0.3020% -0.1443% +0.0093%] (p = 0.08 > 0.05) No change in performance detected. Found 11 outliers among 100 measurements (11.00%) 2 (2.00%) high mild 9 (9.00%) high severe --- src/lizard/lizard_ristretto.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/lizard/lizard_ristretto.rs b/src/lizard/lizard_ristretto.rs index 04fbe0c1..c27989cd 100644 --- a/src/lizard/lizard_ristretto.rs +++ b/src/lizard/lizard_ristretto.rs @@ -131,7 +131,7 @@ impl RistrettoPoint { // such pairs. let mut mask : u8 = 0; - let jcs = self.to_jacobi_quartic_ristretto(); + let (cornerCase, jcs) = self.to_jacobi_quartic_ristretto(); let mut ret = [FieldElement::one(); 8]; for i in 0..4 { @@ -149,6 +149,8 @@ impl RistrettoPoint { mask |= tmp << (2 * i + 1); } + mask.conditional_assign(&(mask & 0b00111111), cornerCase); + return (mask, ret) } @@ -156,8 +158,9 @@ impl RistrettoPoint { /// points Ristretto equivalent to p. /// /// There is one exception: for (0,-1) there is no point on the quartic and - /// so we repeat one on the quartic equivalent to (0,1). - fn to_jacobi_quartic_ristretto(&self) -> [JacobiPoint; 4] { + /// so we repeat one on the quartic equivalent to (0,1). In this case, + /// we repeat one of the points and set the u8 to 1. + fn to_jacobi_quartic_ristretto(&self) -> (Choice, [JacobiPoint; 4]) { let x2 = self.0.X.square(); // X^2 let y2 = self.0.Y.square(); // Y^2 let y4 = y2.square(); // Y^4 @@ -175,7 +178,7 @@ impl RistrettoPoint { let sp_over_xp = &den * &z_pl_y; let s0 = &s_over_x * &self.0.X; - let s1 = &(-(&sp_over_xp)) * &self.0.X; + let mut s1 = &(-(&sp_over_xp)) * &self.0.X; // t_0 := -2/sqrt(-d-1) * Z * sOverX // t_1 := -2/sqrt(-d-1) * Z * spOverXp @@ -195,7 +198,7 @@ impl RistrettoPoint { let sp_over_yp = &den * &iz_pl_x; let mut s2 = &s_over_y * &self.0.Y; - let mut s3 = &(-(&sp_over_yp)) * &self.0.Y; + let s3 = &(-(&sp_over_yp)) * &self.0.Y; // t_2 := -2/sqrt(-d-1) * i*Z * sOverY // t_3 := -2/sqrt(-d-1) * i*Z * spOverYp @@ -210,18 +213,19 @@ impl RistrettoPoint { // Note that if X=0 or Y=0, then s_i = t_i = 0. let x_or_y_is_zero = self.0.X.is_zero() | self.0.Y.is_zero(); t0.conditional_assign(&FieldElement::one(), x_or_y_is_zero); - t1.conditional_assign(&FieldElement::one(), x_or_y_is_zero); + t3.conditional_assign(&FieldElement::one(), x_or_y_is_zero); + t1.conditional_assign(&lizard_constants::MIDOUBLE_INVSQRT_A_MINUS_D, x_or_y_is_zero); t2.conditional_assign(&lizard_constants::MIDOUBLE_INVSQRT_A_MINUS_D, x_or_y_is_zero); - t3.conditional_assign(&lizard_constants::MIDOUBLE_INVSQRT_A_MINUS_D, x_or_y_is_zero); - s2.conditional_assign(&FieldElement::one(), x_or_y_is_zero); - s3.conditional_assign(&(-(&FieldElement::one())), x_or_y_is_zero); + s1.conditional_assign(&FieldElement::one(), x_or_y_is_zero); + s2.conditional_assign(&(-(&FieldElement::one())), x_or_y_is_zero); + - return [ + return (x_or_y_is_zero, [ JacobiPoint{S: s0, T: t0}, JacobiPoint{S: s1, T: t1}, JacobiPoint{S: s2, T: t2}, JacobiPoint{S: s3, T: t3}, - ] + ]) } } @@ -242,7 +246,7 @@ mod test { use super::*; fn test_lizard_encode_helper(data: &[u8; 16], result: &[u8; 32]) { - let p = RistrettoPoint::lizard_encode::(data).unwrap(); + let p = RistrettoPoint::lizard_encode::(data); let p_bytes = p.compress().to_bytes(); assert!(&p_bytes == result); let p = CompressedRistretto::from_slice(&p_bytes).decompress().unwrap();