From 1ef00674b1f97a866930aa0be1bb78c5aa206369 Mon Sep 17 00:00:00 2001 From: SteinerMatthias <86098413+SteinerMatthias@users.noreply.github.com> Date: Fri, 9 Sep 2022 11:10:29 +0200 Subject: [PATCH 1/5] Update scalar.rs implemented Legendre Symbol for BLS12_381 scalar field --- src/scalar.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/scalar.rs b/src/scalar.rs index 84810c8f..b19cd979 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -80,6 +80,15 @@ const MODULUS: Scalar = Scalar([ 0x73ed_a753_299d_7d48, ]); +/// Constant representing (p - 1) / 2 +/// (q - 1) / 2 = 0x39f6d3a994cebea4199cec0404d0ec02a9ded2017fff2dff7fffffff80000000 +const MODULUES_MINUS_ONE_OVER_TWO: [u64; 4] = [ + 0x7fffffff80000000, + 0xa9ded2017fff2dff, + 0x199cec0404d0ec02, + 0x39f6d3a994cebea4 +]; + /// The modulus as u32 limbs. #[cfg(all(feature = "bits", not(target_pointer_width = "64")))] const MODULUS_LIMBS_32: [u32; 8] = [ @@ -343,6 +352,20 @@ impl Scalar { Scalar::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7) } + /// Computes the legendre symbol of this element + pub fn legendre_symbol(&self) -> isize { + let legendre = self.pow(&MODULUES_MINUS_ONE_OVER_TWO); + if legendre == Scalar::zero() { + 0 + } + else if legendre == Scalar::one() { + 1 + } + else { + -1 + } + } + /// Computes the square root of this element, if it exists. pub fn sqrt(&self) -> CtOption { // Tonelli-Shank's algorithm for q mod 16 = 1 @@ -1174,6 +1197,16 @@ fn test_invert_is_pow() { } } +#[test] +fn test_legendre() { + let five = Scalar([5, 0, 0, 0]); + + assert_eq!(Scalar::zero().legendre_symbol(), 0); + assert_eq!(Scalar::one().legendre_symbol(), 1); + assert_eq!((Scalar::one() + Scalar::one()).legendre_symbol(), 1); + assert_eq!(five.legendre_symbol(), -1); +} + #[test] fn test_sqrt() { { From 929a49fbd00d343c1c69e482e74e84bf1f5d278b Mon Sep 17 00:00:00 2001 From: SteinerMatthias <86098413+SteinerMatthias@users.noreply.github.com> Date: Fri, 9 Sep 2022 11:11:40 +0200 Subject: [PATCH 2/5] Update scalar.rs --- src/scalar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scalar.rs b/src/scalar.rs index b19cd979..aad9a44f 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -80,7 +80,7 @@ const MODULUS: Scalar = Scalar([ 0x73ed_a753_299d_7d48, ]); -/// Constant representing (p - 1) / 2 +/// Constant representing (q - 1) / 2 /// (q - 1) / 2 = 0x39f6d3a994cebea4199cec0404d0ec02a9ded2017fff2dff7fffffff80000000 const MODULUES_MINUS_ONE_OVER_TWO: [u64; 4] = [ 0x7fffffff80000000, From 9d6ec0bd9b68044a972d72b9bf8528e5ff8ea367 Mon Sep 17 00:00:00 2001 From: SteinerMatthias <86098413+SteinerMatthias@users.noreply.github.com> Date: Fri, 9 Sep 2022 11:20:01 +0200 Subject: [PATCH 3/5] Update fp.rs implemented Legendre Symbol for BLS12_381 base field --- src/fp.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/fp.rs b/src/fp.rs index 281c66e6..9f5ef88a 100644 --- a/src/fp.rs +++ b/src/fp.rs @@ -76,6 +76,16 @@ const MODULUS: [u64; 6] = [ 0x1a01_11ea_397f_e69a, ]; +/// (p - 1) / 2 = 0xd0088f51cbff34d258dd3db21a5d66bb23ba5c279c2895fb39869507b587b120f55ffff58a9ffffdcff7fffffffd555 +const MODULUES_MINUS_ONE_OVER_TWO: [u64; 6] = [ + 0xdcff7fffffffd555, + 0xf55ffff58a9ffff, + 0xb39869507b587b12, + 0xb23ba5c279c2895f, + 0x258dd3db21a5d66b, + 0xd0088f51cbff34d +]; + /// INV = -(p^{-1} mod 2^64) mod 2^64 const INV: u64 = 0x89f3_fffc_fffc_fffd; @@ -320,6 +330,21 @@ impl Fp { res } + #[inline] + /// Computes the legendre symbol of this element + pub fn legendre_symbol(&self) -> isize { + let legendre = self.pow_vartime(&MODULUES_MINUS_ONE_OVER_TWO); + if legendre == Fp::zero() { + 0 + } + else if legendre == Fp::one() { + 1 + } + else { + -1 + } +} + #[inline] pub fn sqrt(&self) -> CtOption { // We use Shank's method, as p = 3 (mod 4). This means @@ -889,6 +914,16 @@ fn test_from_bytes() { assert!(bool::from(Fp::from_bytes(&[0xff; 48]).is_none())); } +#[test] +fn test_legendre() { + let four = Fp([4, 0, 0, 0, 0, 0]); + + assert_eq!(Fp::zero().legendre_symbol(), 0); + assert_eq!(Fp::one().legendre_symbol(), 1); + assert_eq!((Fp::one() + Fp::one()).legendre_symbol(), -1); + assert_eq!(four.legendre_symbol(), 1); +} + #[test] fn test_sqrt() { // a = 4 From 171105fabd2124b3b2d8b517b2df50deb9433c25 Mon Sep 17 00:00:00 2001 From: SteinerMatthias <86098413+SteinerMatthias@users.noreply.github.com> Date: Fri, 9 Sep 2022 11:22:05 +0200 Subject: [PATCH 4/5] Update fp.rs --- src/fp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fp.rs b/src/fp.rs index 9f5ef88a..715334c5 100644 --- a/src/fp.rs +++ b/src/fp.rs @@ -331,7 +331,7 @@ impl Fp { } #[inline] - /// Computes the legendre symbol of this element + /// Computes the legendre symbol of this element. pub fn legendre_symbol(&self) -> isize { let legendre = self.pow_vartime(&MODULUES_MINUS_ONE_OVER_TWO); if legendre == Fp::zero() { From 3ed85b643198e3251812a258f1567a1674d2ef57 Mon Sep 17 00:00:00 2001 From: SteinerMatthias <86098413+SteinerMatthias@users.noreply.github.com> Date: Fri, 9 Sep 2022 11:25:26 +0200 Subject: [PATCH 5/5] Update scalar.rs --- src/scalar.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scalar.rs b/src/scalar.rs index aad9a44f..e15ff837 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -352,7 +352,7 @@ impl Scalar { Scalar::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7) } - /// Computes the legendre symbol of this element + /// Computes the legendre symbol of this element. pub fn legendre_symbol(&self) -> isize { let legendre = self.pow(&MODULUES_MINUS_ONE_OVER_TWO); if legendre == Scalar::zero() {