From 57b4e7362720b3a2969469ecb16c50058db5083e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michele=20Orr=C3=B9?= Date: Wed, 9 Aug 2017 14:09:54 +0200 Subject: [PATCH] Create enum for LegendreSymbol, fix test. --- src/bls12_381/ec.rs | 2 +- src/bls12_381/fq.rs | 57 +++++++++++++++++--------------------------- src/bls12_381/fq2.rs | 9 +++---- src/bls12_381/fr.rs | 34 ++++++++++++-------------- src/lib.rs | 9 ++++++- 5 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/bls12_381/ec.rs b/src/bls12_381/ec.rs index ae6e9c292..911684469 100644 --- a/src/bls12_381/ec.rs +++ b/src/bls12_381/ec.rs @@ -1480,7 +1480,7 @@ pub mod g2 { if let Some(y) = rhs.sqrt() { let mut negy = y; negy.negate(); - + let p = G2Affine { x: x, y: if y < negy { y } else { negy }, diff --git a/src/bls12_381/fq.rs b/src/bls12_381/fq.rs index 73d1e1632..d2efa0dcf 100644 --- a/src/bls12_381/fq.rs +++ b/src/bls12_381/fq.rs @@ -833,19 +833,14 @@ impl SqrtField for Fq { } impl LegendreField for Fq { - fn legendre(&self) -> i32 { - // (q - 1) / 2 = - // 2001204777610833696708894912867952078278441409969503942666029068062015825245418932221343814564507832018947136279893 - let x = self.pow([0xcff7fffffffd555, 0xf55ffff58a9ffffd, - 0x39869507b587b120, 0x23ba5c279c2895fb, - 0x58dd3db21a5d66bb, 0xd0088f51cbff34d2]); - if x == Self::one() { - 1 - } else if x == Self::zero() { - 0 - } else { - -1 - } + fn legendre(&self) -> ::LegendreSymbol { + use ::LegendreSymbol::*; + + let s = self.pow([0xdcff7fffffffd555, 0xf55ffff58a9ffff, 0xb39869507b587b12, + 0xb23ba5c279c2895f, 0x258dd3db21a5d66b, 0xd0088f51cbff34d]); + if s == Fq::zero() { Zero } + else if s == Fq::one() { QResidue } + else { QNonResidue } } } @@ -1320,12 +1315,12 @@ fn test_fq_sub_assign() { let mut tmp = Fq(FqRepr([0x531221a410efc95b, 0x72819306027e9717, 0x5ecefb937068b746, 0x97de59cd6feaefd7, 0xdc35c51158644588, 0xb2d176c04f2100])); tmp.sub_assign(&Fq(FqRepr([0x98910d20877e4ada, 0x940c983013f4b8ba, 0xf677dc9b8345ba33, 0xbef2ce6b7f577eba, 0xe1ae288ac3222c44, 0x5968bb602790806]))); assert_eq!(tmp, Fq(FqRepr([0x748014838971292c, 0xfd20fad49fddde5c, 0xcf87f198e3d3f336, 0x3d62d6e6e41883db, 0x45a3443cd88dc61b, 0x151d57aaf755ff94]))); - + // Test the opposite subtraction which doesn't test reduction. tmp = Fq(FqRepr([0x98910d20877e4ada, 0x940c983013f4b8ba, 0xf677dc9b8345ba33, 0xbef2ce6b7f577eba, 0xe1ae288ac3222c44, 0x5968bb602790806])); tmp.sub_assign(&Fq(FqRepr([0x531221a410efc95b, 0x72819306027e9717, 0x5ecefb937068b746, 0x97de59cd6feaefd7, 0xdc35c51158644588, 0xb2d176c04f2100]))); assert_eq!(tmp, Fq(FqRepr([0x457eeb7c768e817f, 0x218b052a117621a3, 0x97a8e10812dd02ed, 0x2714749e0f6c8ee3, 0x57863796abde6bc, 0x4e3ba3f4229e706]))); - + // Test for sensible results with zero tmp = Fq(FqRepr::from(0)); tmp.sub_assign(&Fq(FqRepr::from(0))); @@ -1796,29 +1791,21 @@ fn test_fq_ordering() { fn fq_repr_tests() { ::tests::repr::random_repr_tests::(); } + #[test] fn test_fq_legendre() { - assert_eq!(1, Fq::one().legendre()); - assert_eq!(0, Fq::zero().legendre()); + use ::LegendreSymbol::*; - let e = Fq(FqRepr([0x914577fdcc41112, 0x1a6c20f3392c28e2, 0xd53f75da0c40fd21, - 0xb747c10d13caf0d0, 0x0de1adc19c24d8d2, 0x2103f924191033d2])); - assert_eq!(-1, e.legendre()); + assert_eq!(QResidue, Fq::one().legendre()); + assert_eq!(Zero, Fq::zero().legendre()); + assert_eq!(QNonResidue, Fq::from_repr(FqRepr::from(2)).unwrap().legendre()); + assert_eq!(QResidue, Fq::from_repr(FqRepr::from(4)).unwrap().legendre()); - // f - let e = Fq(FqRepr([0xe51d5292ae8126f, 0x382d60874f48db82, 0xb0dde25abc614254, - 0x34f4456bd18813df, 0x2c668010247ee04c, 0x44cb8bbdd7c4f1b0])); - assert_eq!(-1, e.legendre()); - - // f ** 9 - let e = Fq(FqRepr([0x69fc8eb1b590c712, 0xd73f4fb6fd34042e, 0xb5677ef2ed0eede7, - 0x367d831c592848c8, 0xb60615cc44e533f5, 0x127da624461b200e])); - - assert_eq!(-1, e.legendre()); - - let e = Fq(FqRepr([0x83c7ad9e29b7facc, 0x97b3c8fbdb50cc39, 0x9e2ccd0eb5db5e72, - 0xc74a00d90e1b247d, 0x90e38ef46c8d7eb7, 0x16882d6aa70bb469])); - assert_eq!(1, e.legendre()); - + let e = FqRepr([0x52a112f249778642, 0xd0bedb989b7991f, 0xdad3b6681aa63c05, + 0xf2efc0bb4721b283, 0x6057a98f18c24733, 0x1022c2fd122889e4]); + assert_eq!(QNonResidue, Fq::from_repr(e).unwrap().legendre()); + let e = FqRepr([0x6dae594e53a96c74, 0x19b16ca9ba64b37b, 0x5c764661a59bfc68, + 0xaa346e9b31c60a, 0x346059f9d87a9fa9, 0x1d61ac6bfd5c88b]); + assert_eq!(QResidue, Fq::from_repr(e).unwrap().legendre()); } diff --git a/src/bls12_381/fq2.rs b/src/bls12_381/fq2.rs index ecb2965fd..0c9218c3f 100644 --- a/src/bls12_381/fq2.rs +++ b/src/bls12_381/fq2.rs @@ -197,7 +197,7 @@ impl SqrtField for Fq2 { } impl LegendreField for Fq2 { - fn legendre(&self) -> i32 { + fn legendre(&self) -> ::LegendreSymbol { Fq2::norm(&self).legendre() } } @@ -431,13 +431,14 @@ fn test_fq2_sqrt() { #[test] fn test_fq2_legendre() { + use ::LegendreSymbol::*; + // i^2 = -1 let mut m1 = Fq2::one(); m1.negate(); - assert_eq!(1, m1.legendre()); - + assert_eq!(QResidue, m1.legendre()); m1.mul_by_nonresidue(); - assert_eq!(-1, m1.legendre()); + assert_eq!(QNonResidue, m1.legendre()); } #[cfg(test)] diff --git a/src/bls12_381/fr.rs b/src/bls12_381/fr.rs index 40810115d..7842de592 100644 --- a/src/bls12_381/fr.rs +++ b/src/bls12_381/fr.rs @@ -1,4 +1,5 @@ use ::{Field, LegendreField, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError}; +use ::LegendreSymbol::*; // r = 52435875175126190479447740508185965837690552500527637822603658699938581184513 const MODULUS: FrRepr = FrRepr([0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48]); @@ -559,7 +560,7 @@ impl SqrtField for Fr { return Some(*self); } - if self.legendre() != 1 { + if let QNonResidue = self.legendre() { None } else { let mut c = Fr(ROOT_OF_UNITY); @@ -598,16 +599,11 @@ impl SqrtField for Fr { } impl LegendreField for Fr { - fn legendre(&self) -> i32 { - // (q - 1) / 2 = 26217937587563095239723870254092982918845276250263818911301829349969290592256 - let x = self.pow([0x7fffffff80000000, 0xa9ded2017fff2dff, 0x199cec0404d0ec02, 0x39f6d3a994cebea4]); - if x == Self::one() { - 1 - } else if x == Self::zero() { - 0 - } else { - -1 - } + fn legendre(&self) -> ::LegendreSymbol { + let s = self.pow([0x7fffffff80000000, 0xa9ded2017fff2dff, 0x199cec0404d0ec02, 0x39f6d3a994cebea4]); + if s == Self::zero() { Zero } + else if s == Self::one() { QResidue } + else { QNonResidue } } } #[cfg(test)] @@ -792,13 +788,13 @@ fn test_fr_repr_sub_noborrow() { #[test] fn test_fr_legendre() { - assert_eq!(1, Fr::one().legendre()); - assert_eq!(0, Fr::zero().legendre()); + assert_eq!(QResidue, Fr::one().legendre()); + assert_eq!(Zero, Fr::zero().legendre()); - let e = Fr(FrRepr([0x0dbc5349cd5664da, 0x8ac5b6296e3ae29d, 0x127cb819feceaa3b, 0x3a6b21fb03867191])); - assert_eq!(1, e.legendre()); - let e = Fr(FrRepr([0x96341aefd047c045, 0x9b5f4254500a4d65, 0x1ee08223b68ac240, 0x31d9cd545c0ec7c6])); - assert_eq!(-1, e.legendre()); + let e = FrRepr([0x0dbc5349cd5664da, 0x8ac5b6296e3ae29d, 0x127cb819feceaa3b, 0x3a6b21fb03867191]); + assert_eq!(QResidue, Fr::from_repr(e).unwrap().legendre()); + let e = FrRepr([0x96341aefd047c045, 0x9b5f4254500a4d65, 0x1ee08223b68ac240, 0x31d9cd545c0ec7c6]); + assert_eq!(QNonResidue, Fr::from_repr(e).unwrap().legendre()); } #[test] @@ -1038,12 +1034,12 @@ fn test_fr_sub_assign() { let mut tmp = Fr(FrRepr([0x6a68c64b6f735a2b, 0xd5f4d143fe0a1972, 0x37c17f3829267c62, 0xa2f37391f30915c])); tmp.sub_assign(&Fr(FrRepr([0xade5adacdccb6190, 0xaa21ee0f27db3ccd, 0x2550f4704ae39086, 0x591d1902e7c5ba27]))); assert_eq!(tmp, Fr(FrRepr([0xbc83189d92a7f89c, 0x7f908737d62d38a3, 0x45aa62cfe7e4c3e1, 0x24ffc5896108547d]))); - + // Test the opposite subtraction which doesn't test reduction. tmp = Fr(FrRepr([0xade5adacdccb6190, 0xaa21ee0f27db3ccd, 0x2550f4704ae39086, 0x591d1902e7c5ba27])); tmp.sub_assign(&Fr(FrRepr([0x6a68c64b6f735a2b, 0xd5f4d143fe0a1972, 0x37c17f3829267c62, 0xa2f37391f30915c]))); assert_eq!(tmp, Fr(FrRepr([0x437ce7616d580765, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca]))); - + // Test for sensible results with zero tmp = Fr(FrRepr::from(0)); tmp.sub_assign(&Fr(FrRepr::from(0))); diff --git a/src/lib.rs b/src/lib.rs index abd7328e9..0ba79aa9d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -336,7 +336,7 @@ pub trait SqrtField: Field pub trait LegendreField: Field { /// Returns the legendre symbol of the field element. - fn legendre(&self) -> i32; + fn legendre(&self) -> LegendreSymbol; } @@ -417,6 +417,13 @@ pub trait PrimeFieldRepr: Sized + } } +#[derive(Debug, PartialEq)] +pub enum LegendreSymbol { + Zero = 0, + QResidue = 1, + QNonResidue = -1 +} + /// An error that may occur when trying to interpret a `PrimeFieldRepr` as a /// `PrimeField` element. #[derive(Debug)]