From de8b2b24e6730e67ec58d3597af15f7b47a4a0b7 Mon Sep 17 00:00:00 2001 From: Mike Rolish Date: Wed, 21 Aug 2024 09:54:59 -0500 Subject: [PATCH] More tracing --- Cargo.toml | 2 +- src/fields/fp.rs | 32 +++++++++++++++++++------------- src/fields/fp12.rs | 19 +++++++++++++++++++ src/fields/fp2.rs | 3 +++ src/fields/fp6.rs | 3 +++ src/groups/g1.rs | 9 +++++++++ src/groups/g2.rs | 5 +++++ src/lib.rs | 2 +- 8 files changed, 60 insertions(+), 15 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 555e21a..dc63840 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ subtle = "2.6.1" crypto-bigint = "0.6.0-rc.2" sha3 = "0.11.0-pre.4" lazy_static = "1.5.0" - +tracing = "0.1.40" [dev-dependencies] hex-literal = "0.4.1" diff --git a/src/fields/fp.rs b/src/fields/fp.rs index 2fe7ee4..e93bcbc 100644 --- a/src/fields/fp.rs +++ b/src/fields/fp.rs @@ -133,7 +133,8 @@ macro_rules! define_finite_prime_field { //special struct for const-time arithmetic on montgomery form integers mod p type $output = crypto_bigint::modular::ConstMontyForm<$mod_struct, { $mod_struct::LIMBS }>; - #[derive(Clone, Copy, Eq)] //to be used in const contexts + #[derive(Clone, Copy)] //to be used in const contexts + #[derive(Eq)] /// This is the actual struct that serves as our finite field implementation, containing /// the modulus of the field, as well as the output type that contains the internal /// Montgomery arithmetic logic @@ -374,14 +375,14 @@ macro_rules! define_finite_prime_field { if other.is_zero() { return Self::from(0u64); } - let (mut _q, mut _r) = dbg!(self + let (mut _q, mut _r) = self .1 .retrieve() - .div_rem(&NonZero::<$uint_type>::new(other.1.retrieve()).unwrap())); + .div_rem(&NonZero::<$uint_type>::new(other.1.retrieve()).unwrap()); if self.1.retrieve().bit(255).into() { - _q = dbg!(_q - <$uint_type>::ONE); - _r = dbg!(other.1.retrieve() - _r); + _q = _q - <$uint_type>::ONE; + _r = other.1.retrieve() - _r; } Self::new(_q) } @@ -389,14 +390,16 @@ macro_rules! define_finite_prime_field { if other.is_zero() { return Self::from(0u64); } - let (mut _q, mut _r) = dbg!(self + let (mut _q, mut _r) = self .1 .retrieve() - .div_rem(&NonZero::<$uint_type>::new(other.1.retrieve()).unwrap())); + .div_rem(&NonZero::<$uint_type>::new(other.1.retrieve()).unwrap()); + tracing::debug!(?_q, ?_r, "finite_prime_field::rem_euclid"); if self.1.retrieve().bit(255).into() { // _q = _q - <$uint_type>::ONE; - _r = dbg!(other.1.retrieve() - _r); + _r = other.1.retrieve() - _r; + tracing::debug!(?_r, "finite_prime_field::rem_euclid high bit"); } Self::new(_r) } @@ -469,8 +472,9 @@ impl Fp { /// possible solution of $\pm pow(n, \frac{p+1}{4})$, which is where this magic /// number below comes from ;) pub fn sqrt(&self) -> CtOption { - let arg = dbg!((Self::new(Self::characteristic()) + Self::one()) / Self::from(4)).value(); - let sqrt = dbg!(self.pow(arg)); + let arg = ((Self::new(Self::characteristic()) + Self::one()) / Self::from(4)).value(); + let sqrt = self.pow(arg); + tracing::debug!(?arg, ?sqrt, "Fp::sqrt"); CtOption::new(sqrt, sqrt.square().ct_eq(self)) } /// Returns the square of the element in the base field @@ -480,14 +484,16 @@ impl Fp { /// Determines if the element in the base field is a square of another element pub fn is_square(&self) -> Choice { let p_minus_1_div_2 = - dbg!((Self::new(Self::characteristic()) - Self::from(1)) / Self::from(2)).value(); - let retval = dbg!(self.pow(p_minus_1_div_2)); + ((Self::new(Self::characteristic()) - Self::from(1)) / Self::from(2)).value(); + let retval = self.pow(p_minus_1_div_2); + tracing::debug!(?p_minus_1_div_2, ?retval, "Fp::is_square"); Choice::from((retval == Self::zero() || retval == Self::one()) as u8) } /// Determines the 'sign' of a value in the base field, /// see for more details pub fn sgn0(&self) -> Choice { - let a = dbg!(*self % Self::from(2u64)); + let a = *self % Self::from(2u64); + tracing::debug!(?a, "Fp::sgn0"); if a.is_zero() { Choice::from(0u8) } else { diff --git a/src/fields/fp12.rs b/src/fields/fp12.rs index c3d42a8..2a4d3b4 100644 --- a/src/fields/fp12.rs +++ b/src/fields/fp12.rs @@ -201,6 +201,7 @@ impl<'a, 'b> Mul<&'b Fp12> for &'a Fp12 { // let t0 = self.0[0] * other.0[0]; let t1 = self.0[1] * other.0[1]; + tracing::debug!(?t0, ?t1, "Fp12::mul"); Self::Output::new(&[ t1.residue_mul() + t0, @@ -224,6 +225,7 @@ impl Inv for Fp12 { fn inv(self) -> Self::Output { // Implements Alg 23 of let tmp = (self.0[0].square() - (self.0[1].square().residue_mul())).inv(); + tracing::debug!(?tmp, "Fp12::inv"); Self([self.0[0] * tmp, -(self.0[1] * tmp)]) } } @@ -304,10 +306,12 @@ impl Fp12 { let z3 = self.0[1].0[0]; let z4 = self.0[1].0[1]; let z5 = self.0[1].0[2]; + tracing::debug!(?z0, ?z1, ?z2, ?z3, ?z4, ?z5, "Fp12::sparse_mul"); let x0 = ell_0; let x2 = ell_vv; let x4 = ell_vw; + tracing::debug!(?x0, ?x2, ?x4, "Fp12::sparse_mul"); let d0 = z0 * x0; let d2 = z2 * x2; @@ -315,49 +319,61 @@ impl Fp12 { let t2 = z0 + z4; let t1 = z0 + z2; let s0 = z1 + z3 + z5; + tracing::debug!(?d0, ?d2, ?d4, ?t2, ?t1, ?s0, "Fp12::sparse_mul"); let s1 = z1 * x2; let t3 = s1 + d4; let t4 = t3.residue_mul() + d0; let z0 = t4; + tracing::debug!(?s1, ?t2, ?t4, ?z0, "Fp12::sparse_mul"); let t3 = z5 * x4; let s1 = s1 + t3; + tracing::debug!(?t3, ?s1, "Fp12::sparse_mul"); let t3 = t3 + d2; let t4 = t3.residue_mul(); + tracing::debug!(?t3, ?t4, "Fp12::sparse_mul"); let t3 = z1 * x0; let s1 = s1 + t3; let t4 = t4 + t3; let z1 = t4; + tracing::debug!(?t3, ?s1, ?t4, ?z1, "Fp12::sparse_mul"); let t0 = x0 + x2; let t3 = t1 * t0 - d0 - d2; let t4 = z3 * x4; let s1 = s1 + t4; let t3 = t3 + t4; + tracing::debug!(?t0, ?t3, ?t4, ?s1, ?t3, "Fp12::sparse_mul"); let t0 = z2 + z4; let z2 = t3; + tracing::debug!(?t0, ?z2, "Fp12::sparse_mul"); let t1 = x2 + x4; let t3 = t0 * t1 - d2 - d4; let t4 = t3.residue_mul(); + tracing::debug!(?t1, ?t3, ?t4, "Fp12::sparse_mul"); let t3 = z3 * x0; let s1 = s1 + t3; let t4 = t4 + t3; let z3 = t4; + tracing::debug!(?t3, ?s1, ?t4, ?z3, "Fp12::sparse_mul"); let t3 = z5 * x2; let s1 = s1 + t3; let t4 = t3.residue_mul(); let t0 = x0 + x4; + tracing::debug!(?t3, ?s1, ?t4, ?t0, "Fp12::sparse_mul"); let t3 = t2 * t0 - d0 - d4; let t4 = t4 + t3; let z4 = t4; + tracing::debug!(?t3, ?t4, ?z4, "Fp12::sparse_mul"); let t0 = x0 + x2 + x4; let t3 = s0 * t0 - s1; let z5 = t3; + tracing::debug!(?t0, ?t3, ?z5, "Fp12::sparse_mul"); Fp12::new(&[Fp6::new(&[z0, z1, z2]), Fp6::new(&[z3, z4, z5])]) } @@ -376,10 +392,13 @@ impl Fp12 { let c0 = self.0[0] - self.0[1]; let c3 = self.0[0] - self.0[1].residue_mul(); let c2 = self.0[0] * self.0[1]; + tracing::debug!(?c0, ?c2, ?c3, "Fp12::square 1"); let c0 = c0 * c3 + c2; let c1 = c2 + c2; let c2 = c2.residue_mul(); + tracing::debug!(?c0, ?c1, ?c2, "Fp12::square 2"); let c0 = c0 + c2; + tracing::debug!(?c0, "Fp12::square 3"); Self::new(&[c0, c1]) } } diff --git a/src/fields/fp2.rs b/src/fields/fp2.rs index d7c1acb..dcb2ba8 100644 --- a/src/fields/fp2.rs +++ b/src/fields/fp2.rs @@ -101,6 +101,7 @@ impl Fp2 { if a0 == -Fp2::one() { return CtOption::new(Fp2::zero(), Choice::from(0u8)); } + tracing::debug!(?alpha, ?a0, "Fp2::sqrt"); if alpha == -Fp2::one() { let i = Fp2::new(&[Fp::ZERO, Fp::ONE]); @@ -114,6 +115,7 @@ impl Fp2 { } pub fn square(&self) -> Self { let t0 = self.0[0] * self.0[1]; + tracing::debug!(?t0, "Fp2::square"); Self([ (self.0[1] * >::quadratic_non_residue() + self.0[0]) * (self.0[0] + self.0[1]) @@ -136,6 +138,7 @@ impl Fp2 { }; let sum = self.0[0].square() + >::quadratic_non_residue() * (-self.0[0]).square(); + tracing::debug!(?sum, "Fp2::is_square"); Choice::from((legendre(&sum) != -1) as u8) } pub fn sgn0(&self) -> Choice { diff --git a/src/fields/fp6.rs b/src/fields/fp6.rs index 7da0f74..ca98fb1 100644 --- a/src/fields/fp6.rs +++ b/src/fields/fp6.rs @@ -199,6 +199,7 @@ impl Fp6 { let s3 = bc + bc; let mut s4 = self.0[2]; s4 = s4.square(); + tracing::debug!(?t0, ?cross, ?t1, ?t2, ?bc, ?s3, ?s4, "Fp6::square"); Self([ t0 + s3.residue_mul(), @@ -231,6 +232,7 @@ impl<'a, 'b> Mul<&'b Fp6> for &'a Fp6 { let t0 = self.0[0] * other.0[0]; let t1 = self.0[1] * other.0[1]; let t2 = self.0[2] * other.0[2]; + tracing::debug!(?t0, ?t1, ?t2, "Fp6::mul"); Self::Output::new(&[ ((self.0[1] + self.0[2]) * (other.0[1] + other.0[2]) - t1 - t2).residue_mul() + t0, @@ -260,6 +262,7 @@ impl Inv for Fp6 { let t2 = self.0[1].square() - self.0[0] * self.0[2]; let inverse = ((self.0[2] * t1 + self.0[1] * t2).residue_mul() + self.0[0] * t0).inv(); + tracing::debug!(?t0, ?t1, ?t2, ?inverse, "Fp6::inv"); Self([inverse * t0, inverse * t1, inverse * t2]) } } diff --git a/src/groups/g1.rs b/src/groups/g1.rs index 77a43ec..39c0390 100644 --- a/src/groups/g1.rs +++ b/src/groups/g1.rs @@ -77,6 +77,7 @@ impl G1Affine { let x2 = x.square(); let lhs = y2 - (x2 * (*x)); let rhs = >::curve_constant(); + tracing::debug!(?y2, ?x2, ?lhs, ?rhs, "G1Affine::new"); lhs.ct_eq(&rhs) | *z }; @@ -85,10 +86,12 @@ impl G1Affine { Choice::from(1u8) }; let is_on_curve: Choice = _g1affine_is_on_curve(&v[0], &v[1], &Choice::from(0u8)); + tracing::debug!(?is_on_curve, "G1Affine::new"); match bool::from(is_on_curve) { true => { let is_in_torsion: Choice = _g1affine_is_torsion_free(&v[0], &v[1], &Choice::from(0u8)); + tracing::debug!(?is_in_torsion, "G1Affine::new"); match bool::from(is_in_torsion) { true => Ok(Self { x: v[0], @@ -123,6 +126,7 @@ impl GroupTrait<1, 1, Fp> for G1Projective { let scalars = exp .hash_to_field(msg, COUNT, L) .expect("Hashing to base field failed"); + tracing::debug!(?scalars, "GroupTrait::hash_to_curve"); match SvdW::precompute_constants(Fp::from(0), Fp::from(3)) { Ok(bn254_g1_svdw) => { let a = G1Projective::from( @@ -135,6 +139,7 @@ impl GroupTrait<1, 1, Fp> for G1Projective { .unchecked_map_to_point(scalars[1]) .expect("Failed to hash"), ); + tracing::debug!(?a, ?b, "GroupTrait::hash_to_curve"); Ok(a + b) } _ => Err(GroupError::CannotHashToGroup), @@ -151,6 +156,7 @@ impl GroupTrait<1, 1, Fp> for G1Projective { .iter() .map(|x| x.frobenius(exponent)) .collect(); + tracing::debug!(?vec, "GroupTrait::frobenius"); Self { x: vec[0], y: vec[1], @@ -171,14 +177,17 @@ impl G1Projective { let z2 = z.square(); let lhs = y2 * (*z); let rhs = x2 * (*x) + z2 * (*z) * >::curve_constant(); + tracing::debug!(?y2, ?x2, ?z2, ?lhs, ?rhs, "G1Projective::new"); lhs.ct_eq(&rhs) | Choice::from(z.is_zero() as u8) }; let _g1projective_is_torsion_free = |_x: &Fp, _y: &Fp, _z: &Fp| -> Choice { Choice::from(1u8) }; let is_on_curve: Choice = _g1projective_is_on_curve(&v[0], &v[1], &v[2]); + tracing::debug!(?is_on_curve, "G1Projective::new"); match bool::from(is_on_curve) { true => { let is_in_torsion: Choice = _g1projective_is_torsion_free(&v[0], &v[1], &v[2]); + tracing::debug!(?is_in_torsion, "G1Projective::new"); match bool::from(is_in_torsion) { true => Ok(Self { x: v[0], diff --git a/src/groups/g2.rs b/src/groups/g2.rs index a833e28..5bfd715 100644 --- a/src/groups/g2.rs +++ b/src/groups/g2.rs @@ -117,6 +117,7 @@ impl GroupTrait<2, 2, Fp2> for G2Affine { let x_endo = EPS_EXP0 * x_frob; let y_endo = EPS_EXP1 * y_frob; + tracing::debug!(?x_frob, ?y_frob, ?x_endo, ?y_endo, "G2Affine::endomorphism"); Self::new_unchecked([x_endo, y_endo]).expect("Endomorphism failed") } @@ -177,6 +178,7 @@ impl GroupTrait<2, 2, Fp2> for G2Projective { ])); let rando = Fp::new(Fr::rand(rng).value()); let mut tmp = Self::generator() * rando; + tracing::debug!(?rando, ?tmp, "G2Projective::rand"); // multiplying an element of the larger base field by the cofactor of a prime-ordered // subgroup will return an element in the prime-order subgroup, see @@ -222,6 +224,7 @@ impl G2Affine { let x2 = x.square(); let lhs = y2 - (x2 * (*x)); let rhs = >::curve_constant(); + tracing::debug!(?y2, ?x2, ?lhs, ?rhs, "G2Affine::new_unchecked"); lhs.ct_eq(&rhs) | *z }; @@ -250,6 +253,7 @@ impl G2Projective { let z2 = z.square(); let lhs = y2 * (*z); let rhs = x2 * (*x) + z2 * (*z) * >::curve_constant(); + tracing::debug!(?y2, ?x2, ?z2, ?lhs, ?rhs, "G2Projective::new"); lhs.ct_eq(&rhs) | Choice::from(z.is_zero() as u8) }; // This method is where the magic happens. In a naïve approach, in order to check for @@ -287,6 +291,7 @@ impl G2Projective { let mut rhs = b.endomorphism(); // ψ^2(xQ) let lhs = rhs + b + a; // ψ^2(xQ) + ψ(xQ) + (x+1)Q rhs = rhs.endomorphism().double() - lhs; // ψ^3(2xQ) - (ψ^2(xQ) + ψ(xQ) + (x+1)Q) + tracing::debug!(?x, ?y, ?z, ?a, ?b, ?lhs, ?rhs, "G2Projective::_g2projective_is_torsion_free"); // we do two checks: one is to verify that the result is indeed a point at infinity, // but we need a second check to verify that it is OUR point at infinity, namely for diff --git a/src/lib.rs b/src/lib.rs index e83b105..03c1689 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,7 +64,7 @@ pub fn sign(k: &Fp, msg: &[u8]) -> Result { } } -/// This takes a pub lic key, message, and a signature, and verifies that the signature is valid +/// This takes a public key, message, and a signature, and verifies that the signature is valid pub fn verify(pubkey: &G2Projective, msg: &[u8], sig: &G1Projective) -> Result { let expander = XMDExpander::::new(DST, SECURITY_BITS); match G1Projective::hash_to_curve(&expander, msg) {