Auto merge of #77 - ebfull:rustfmt-application-2, r=ebfull

Apply rustfmt

Supersedes #76

I've made a change to the CI which checks `rustfmt` against the code. Let's see if it worked.
This commit is contained in:
bmerge
2018-03-05 02:49:40 +00:00
14 changed files with 3485 additions and 827 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,17 @@
use rand::{Rng, Rand}; use rand::{Rand, Rng};
use ::{Field}; use Field;
use super::fq6::Fq6; use super::fq6::Fq6;
use super::fq2::Fq2; use super::fq2::Fq2;
use super::fq::{FROBENIUS_COEFF_FQ12_C1}; use super::fq::FROBENIUS_COEFF_FQ12_C1;
/// An element of Fq12, represented by c0 + c1 * w. /// An element of Fq12, represented by c0 + c1 * w.
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Fq12 { pub struct Fq12 {
pub c0: Fq6, pub c0: Fq6,
pub c1: Fq6 pub c1: Fq6,
} }
impl ::std::fmt::Display for Fq12 impl ::std::fmt::Display for Fq12 {
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fq12({} + {} * w)", self.c0, self.c1) write!(f, "Fq12({} + {} * w)", self.c0, self.c1)
} }
@@ -22,24 +21,17 @@ impl Rand for Fq12 {
fn rand<R: Rng>(rng: &mut R) -> Self { fn rand<R: Rng>(rng: &mut R) -> Self {
Fq12 { Fq12 {
c0: rng.gen(), c0: rng.gen(),
c1: rng.gen() c1: rng.gen(),
} }
} }
} }
impl Fq12 { impl Fq12 {
pub fn conjugate(&mut self) pub fn conjugate(&mut self) {
{
self.c1.negate(); self.c1.negate();
} }
pub fn mul_by_014( pub fn mul_by_014(&mut self, c0: &Fq2, c1: &Fq2, c4: &Fq2) {
&mut self,
c0: &Fq2,
c1: &Fq2,
c4: &Fq2
)
{
let mut aa = self.c0; let mut aa = self.c0;
aa.mul_by_01(c0, c1); aa.mul_by_01(c0, c1);
let mut bb = self.c1; let mut bb = self.c1;
@@ -56,19 +48,18 @@ impl Fq12 {
} }
} }
impl Field for Fq12 impl Field for Fq12 {
{
fn zero() -> Self { fn zero() -> Self {
Fq12 { Fq12 {
c0: Fq6::zero(), c0: Fq6::zero(),
c1: Fq6::zero() c1: Fq6::zero(),
} }
} }
fn one() -> Self { fn one() -> Self {
Fq12 { Fq12 {
c0: Fq6::one(), c0: Fq6::one(),
c1: Fq6::zero() c1: Fq6::zero(),
} }
} }
@@ -96,8 +87,7 @@ impl Field for Fq12
self.c1.sub_assign(&other.c1); self.c1.sub_assign(&other.c1);
} }
fn frobenius_map(&mut self, power: usize) fn frobenius_map(&mut self, power: usize) {
{
self.c0.frobenius_map(power); self.c0.frobenius_map(power);
self.c1.frobenius_map(power); self.c1.frobenius_map(power);
@@ -148,10 +138,7 @@ impl Field for Fq12
c0s.sub_assign(&c1s); c0s.sub_assign(&c1s);
c0s.inverse().map(|t| { c0s.inverse().map(|t| {
let mut tmp = Fq12 { let mut tmp = Fq12 { c0: t, c1: t };
c0: t,
c1: t
};
tmp.c0.mul_assign(&self.c0); tmp.c0.mul_assign(&self.c0);
tmp.c1.mul_assign(&self.c1); tmp.c1.mul_assign(&self.c1);
tmp.c1.negate(); tmp.c1.negate();
@@ -180,13 +167,13 @@ fn test_fq12_mul_by_014() {
c0: Fq6 { c0: Fq6 {
c0: c0, c0: c0,
c1: c1, c1: c1,
c2: Fq2::zero() c2: Fq2::zero(),
}, },
c1: Fq6 { c1: Fq6 {
c0: Fq2::zero(), c0: Fq2::zero(),
c1: c5, c1: c5,
c2: Fq2::zero() c2: Fq2::zero(),
} },
}); });
assert_eq!(a, b); assert_eq!(a, b);
@@ -195,7 +182,7 @@ fn test_fq12_mul_by_014() {
#[test] #[test]
fn fq12_field_tests() { fn fq12_field_tests() {
use ::PrimeField; use PrimeField;
::tests::field::random_field_tests::<Fq12>(); ::tests::field::random_field_tests::<Fq12>();
::tests::field::random_frobenius_tests::<Fq12, _>(super::fq::Fq::char(), 13); ::tests::field::random_frobenius_tests::<Fq12, _>(super::fq::Fq::char(), 13);

View File

@@ -1,6 +1,6 @@
use rand::{Rng, Rand}; use rand::{Rand, Rng};
use ::{Field, SqrtField}; use {Field, SqrtField};
use super::fq::{Fq, FROBENIUS_COEFF_FQ2_C1, NEGATIVE_ONE}; use super::fq::{FROBENIUS_COEFF_FQ2_C1, Fq, NEGATIVE_ONE};
use std::cmp::Ordering; use std::cmp::Ordering;
@@ -8,11 +8,10 @@ use std::cmp::Ordering;
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Fq2 { pub struct Fq2 {
pub c0: Fq, pub c0: Fq,
pub c1: Fq pub c1: Fq,
} }
impl ::std::fmt::Display for Fq2 impl ::std::fmt::Display for Fq2 {
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fq2({} + {} * u)", self.c0, self.c1) write!(f, "Fq2({} + {} * u)", self.c0, self.c1)
} }
@@ -25,7 +24,7 @@ impl Ord for Fq2 {
match self.c1.cmp(&other.c1) { match self.c1.cmp(&other.c1) {
Ordering::Greater => Ordering::Greater, Ordering::Greater => Ordering::Greater,
Ordering::Less => Ordering::Less, Ordering::Less => Ordering::Less,
Ordering::Equal => self.c0.cmp(&other.c0) Ordering::Equal => self.c0.cmp(&other.c0),
} }
} }
} }
@@ -61,18 +60,24 @@ impl Rand for Fq2 {
fn rand<R: Rng>(rng: &mut R) -> Self { fn rand<R: Rng>(rng: &mut R) -> Self {
Fq2 { Fq2 {
c0: rng.gen(), c0: rng.gen(),
c1: rng.gen() c1: rng.gen(),
} }
} }
} }
impl Field for Fq2 { impl Field for Fq2 {
fn zero() -> Self { fn zero() -> Self {
Fq2 { c0: Fq::zero(), c1: Fq::zero() } Fq2 {
c0: Fq::zero(),
c1: Fq::zero(),
}
} }
fn one() -> Self { fn one() -> Self {
Fq2 { c0: Fq::one(), c1: Fq::zero() } Fq2 {
c0: Fq::one(),
c1: Fq::zero(),
}
} }
fn is_zero(&self) -> bool { fn is_zero(&self) -> bool {
@@ -139,7 +144,7 @@ impl Field for Fq2 {
t0.inverse().map(|t| { t0.inverse().map(|t| {
let mut tmp = Fq2 { let mut tmp = Fq2 {
c0: self.c0, c0: self.c0,
c1: self.c1 c1: self.c1,
}; };
tmp.c0.mul_assign(&t); tmp.c0.mul_assign(&t);
tmp.c1.mul_assign(&t); tmp.c1.mul_assign(&t);
@@ -149,14 +154,12 @@ impl Field for Fq2 {
}) })
} }
fn frobenius_map(&mut self, power: usize) fn frobenius_map(&mut self, power: usize) {
{
self.c1.mul_assign(&FROBENIUS_COEFF_FQ2_C1[power % 2]); self.c1.mul_assign(&FROBENIUS_COEFF_FQ2_C1[power % 2]);
} }
} }
impl SqrtField for Fq2 { impl SqrtField for Fq2 {
fn legendre(&self) -> ::LegendreSymbol { fn legendre(&self) -> ::LegendreSymbol {
self.norm().legendre() self.norm().legendre()
} }
@@ -168,7 +171,14 @@ impl SqrtField for Fq2 {
Some(Self::zero()) Some(Self::zero())
} else { } else {
// a1 = self^((q - 3) / 4) // a1 = self^((q - 3) / 4)
let mut a1 = self.pow([0xee7fbfffffffeaaa, 0x7aaffffac54ffff, 0xd9cc34a83dac3d89, 0xd91dd2e13ce144af, 0x92c6e9ed90d2eb35, 0x680447a8e5ff9a6]); let mut a1 = self.pow([
0xee7fbfffffffeaaa,
0x7aaffffac54ffff,
0xd9cc34a83dac3d89,
0xd91dd2e13ce144af,
0x92c6e9ed90d2eb35,
0x680447a8e5ff9a6,
]);
let mut alpha = a1; let mut alpha = a1;
alpha.square(); alpha.square();
alpha.mul_assign(self); alpha.mul_assign(self);
@@ -178,7 +188,7 @@ impl SqrtField for Fq2 {
let neg1 = Fq2 { let neg1 = Fq2 {
c0: NEGATIVE_ONE, c0: NEGATIVE_ONE,
c1: Fq::zero() c1: Fq::zero(),
}; };
if a0 == neg1 { if a0 == neg1 {
@@ -187,11 +197,21 @@ impl SqrtField for Fq2 {
a1.mul_assign(self); a1.mul_assign(self);
if alpha == neg1 { if alpha == neg1 {
a1.mul_assign(&Fq2{c0: Fq::zero(), c1: Fq::one()}); a1.mul_assign(&Fq2 {
c0: Fq::zero(),
c1: Fq::one(),
});
} else { } else {
alpha.add_assign(&Fq2::one()); alpha.add_assign(&Fq2::one());
// alpha = alpha^((q - 1) / 2) // alpha = alpha^((q - 1) / 2)
alpha = alpha.pow([0xdcff7fffffffd555, 0xf55ffff58a9ffff, 0xb39869507b587b12, 0xb23ba5c279c2895f, 0x258dd3db21a5d66b, 0xd0088f51cbff34d]); alpha = alpha.pow([
0xdcff7fffffffd555,
0xf55ffff58a9ffff,
0xb39869507b587b12,
0xb23ba5c279c2895f,
0x258dd3db21a5d66b,
0xd0088f51cbff34d,
]);
a1.mul_assign(&alpha); a1.mul_assign(&alpha);
} }
@@ -205,7 +225,7 @@ impl SqrtField for Fq2 {
fn test_fq2_ordering() { fn test_fq2_ordering() {
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::zero(), c0: Fq::zero(),
c1: Fq::zero() c1: Fq::zero(),
}; };
let mut b = a.clone(); let mut b = a.clone();
@@ -227,210 +247,625 @@ fn test_fq2_ordering() {
#[test] #[test]
fn test_fq2_basics() { fn test_fq2_basics() {
assert_eq!(Fq2 { c0: Fq::zero(), c1: Fq::zero() }, Fq2::zero()); assert_eq!(
assert_eq!(Fq2 { c0: Fq::one(), c1: Fq::zero() }, Fq2::one()); Fq2 {
c0: Fq::zero(),
c1: Fq::zero(),
},
Fq2::zero()
);
assert_eq!(
Fq2 {
c0: Fq::one(),
c1: Fq::zero(),
},
Fq2::one()
);
assert!(Fq2::zero().is_zero()); assert!(Fq2::zero().is_zero());
assert!(!Fq2::one().is_zero()); assert!(!Fq2::one().is_zero());
assert!(!Fq2{c0: Fq::zero(), c1: Fq::one()}.is_zero()); assert!(!Fq2 {
c0: Fq::zero(),
c1: Fq::one(),
}.is_zero());
} }
#[test] #[test]
fn test_fq2_squaring() { fn test_fq2_squaring() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { c0: Fq::one(), c1: Fq::one() }; // u + 1 let mut a = Fq2 {
c0: Fq::one(),
c1: Fq::one(),
}; // u + 1
a.square(); a.square();
assert_eq!(a, Fq2 { c0: Fq::zero(), c1: Fq::from_repr(FqRepr::from(2)).unwrap() }); // 2u assert_eq!(
a,
Fq2 {
c0: Fq::zero(),
c1: Fq::from_repr(FqRepr::from(2)).unwrap(),
}
); // 2u
let mut a = Fq2 { c0: Fq::zero(), c1: Fq::one() }; // u let mut a = Fq2 {
c0: Fq::zero(),
c1: Fq::one(),
}; // u
a.square(); a.square();
assert_eq!(a, { assert_eq!(a, {
let mut neg1 = Fq::one(); let mut neg1 = Fq::one();
neg1.negate(); neg1.negate();
Fq2 { c0: neg1, c1: Fq::zero() } Fq2 {
c0: neg1,
c1: Fq::zero(),
}
}); // -1 }); // -1
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x9c2c6309bbf8b598, 0x4eef5c946536f602, 0x90e34aab6fb6a6bd, 0xf7f295a94e58ae7c, 0x41b76dcc1c3fbe5e, 0x7080c5fa1d8e042])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x38f473b3c870a4ab, 0x6ad3291177c8c7e5, 0xdac5a4c911a4353e, 0xbfb99020604137a0, 0xfc58a7b7be815407, 0x10d1615e75250a21])).unwrap() 0x9c2c6309bbf8b598,
0x4eef5c946536f602,
0x90e34aab6fb6a6bd,
0xf7f295a94e58ae7c,
0x41b76dcc1c3fbe5e,
0x7080c5fa1d8e042,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x38f473b3c870a4ab,
0x6ad3291177c8c7e5,
0xdac5a4c911a4353e,
0xbfb99020604137a0,
0xfc58a7b7be815407,
0x10d1615e75250a21,
])).unwrap(),
}; };
a.square(); a.square();
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0xf262c28c538bcf68, 0xb9f2a66eae1073ba, 0xdc46ab8fad67ae0, 0xcb674157618da176, 0x4cf17b5893c3d327, 0x7eac81369c43361])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0xc1579cf58e980cf8, 0xa23eb7e12dd54d98, 0xe75138bce4cec7aa, 0x38d0d7275a9689e1, 0x739c983042779a65, 0x1542a61c8a8db994])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0xf262c28c538bcf68,
0xb9f2a66eae1073ba,
0xdc46ab8fad67ae0,
0xcb674157618da176,
0x4cf17b5893c3d327,
0x7eac81369c43361
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xc1579cf58e980cf8,
0xa23eb7e12dd54d98,
0xe75138bce4cec7aa,
0x38d0d7275a9689e1,
0x739c983042779a65,
0x1542a61c8a8db994
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_mul() { fn test_fq2_mul() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x85c9f989e1461f03, 0xa2e33c333449a1d6, 0x41e461154a7354a3, 0x9ee53e7e84d7532e, 0x1c202d8ed97afb45, 0x51d3f9253e2516f])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0xa7348a8b511aedcf, 0x143c215d8176b319, 0x4cc48081c09b8903, 0x9533e4a9a5158be, 0x7a5e1ecb676d65f9, 0x180c3ee46656b008])).unwrap() 0x85c9f989e1461f03,
0xa2e33c333449a1d6,
0x41e461154a7354a3,
0x9ee53e7e84d7532e,
0x1c202d8ed97afb45,
0x51d3f9253e2516f,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xa7348a8b511aedcf,
0x143c215d8176b319,
0x4cc48081c09b8903,
0x9533e4a9a5158be,
0x7a5e1ecb676d65f9,
0x180c3ee46656b008,
])).unwrap(),
}; };
a.mul_assign(&Fq2 { a.mul_assign(&Fq2 {
c0: Fq::from_repr(FqRepr([0xe21f9169805f537e, 0xfc87e62e179c285d, 0x27ece175be07a531, 0xcd460f9f0c23e430, 0x6c9110292bfa409, 0x2c93a72eb8af83e])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x4b1c3f936d8992d4, 0x1d2a72916dba4c8a, 0x8871c508658d1e5f, 0x57a06d3135a752ae, 0x634cd3c6c565096d, 0x19e17334d4e93558])).unwrap() 0xe21f9169805f537e,
}); 0xfc87e62e179c285d,
assert_eq!(a, Fq2 { 0x27ece175be07a531,
c0: Fq::from_repr(FqRepr([0x95b5127e6360c7e4, 0xde29c31a19a6937e, 0xf61a96dacf5a39bc, 0x5511fe4d84ee5f78, 0x5310a202d92f9963, 0x1751afbe166e5399])).unwrap(), 0xcd460f9f0c23e430,
c1: Fq::from_repr(FqRepr([0x84af0e1bd630117a, 0x6c63cd4da2c2aa7, 0x5ba6e5430e883d40, 0xc975106579c275ee, 0x33a9ac82ce4c5083, 0x1ef1a36c201589d])).unwrap() 0x6c9110292bfa409,
0x2c93a72eb8af83e,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x4b1c3f936d8992d4,
0x1d2a72916dba4c8a,
0x8871c508658d1e5f,
0x57a06d3135a752ae,
0x634cd3c6c565096d,
0x19e17334d4e93558,
])).unwrap(),
}); });
assert_eq!(
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x95b5127e6360c7e4,
0xde29c31a19a6937e,
0xf61a96dacf5a39bc,
0x5511fe4d84ee5f78,
0x5310a202d92f9963,
0x1751afbe166e5399
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x84af0e1bd630117a,
0x6c63cd4da2c2aa7,
0x5ba6e5430e883d40,
0xc975106579c275ee,
0x33a9ac82ce4c5083,
0x1ef1a36c201589d
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_inverse() { fn test_fq2_inverse() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
assert!(Fq2::zero().inverse().is_none()); assert!(Fq2::zero().inverse().is_none());
let a = Fq2 { let a = Fq2 {
c0: Fq::from_repr(FqRepr([0x85c9f989e1461f03, 0xa2e33c333449a1d6, 0x41e461154a7354a3, 0x9ee53e7e84d7532e, 0x1c202d8ed97afb45, 0x51d3f9253e2516f])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0xa7348a8b511aedcf, 0x143c215d8176b319, 0x4cc48081c09b8903, 0x9533e4a9a5158be, 0x7a5e1ecb676d65f9, 0x180c3ee46656b008])).unwrap() 0x85c9f989e1461f03,
0xa2e33c333449a1d6,
0x41e461154a7354a3,
0x9ee53e7e84d7532e,
0x1c202d8ed97afb45,
0x51d3f9253e2516f,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xa7348a8b511aedcf,
0x143c215d8176b319,
0x4cc48081c09b8903,
0x9533e4a9a5158be,
0x7a5e1ecb676d65f9,
0x180c3ee46656b008,
])).unwrap(),
}; };
let a = a.inverse().unwrap(); let a = a.inverse().unwrap();
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x70300f9bcb9e594, 0xe5ecda5fdafddbb2, 0x64bef617d2915a8f, 0xdfba703293941c30, 0xa6c3d8f9586f2636, 0x1351ef01941b70c4])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x8c39fd76a8312cb4, 0x15d7b6b95defbff0, 0x947143f89faedee9, 0xcbf651a0f367afb2, 0xdf4e54f0d3ef15a6, 0x103bdf241afb0019])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x70300f9bcb9e594,
0xe5ecda5fdafddbb2,
0x64bef617d2915a8f,
0xdfba703293941c30,
0xa6c3d8f9586f2636,
0x1351ef01941b70c4
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x8c39fd76a8312cb4,
0x15d7b6b95defbff0,
0x947143f89faedee9,
0xcbf651a0f367afb2,
0xdf4e54f0d3ef15a6,
0x103bdf241afb0019
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_addition() { fn test_fq2_addition() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() 0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
])).unwrap(),
}; };
a.add_assign(&Fq2 { a.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr([0x619a02d78dc70ef2, 0xb93adfc9119e33e8, 0x4bf0b99a9f0dca12, 0x3b88899a42a6318f, 0x986a4a62fa82a49d, 0x13ce433fa26027f5])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x66323bf80b58b9b9, 0xa1379b6facf6e596, 0x402aef1fb797e32f, 0x2236f55246d0d44d, 0x4c8c1800eb104566, 0x11d6e20e986c2085])).unwrap() 0x619a02d78dc70ef2,
}); 0xb93adfc9119e33e8,
assert_eq!(a, Fq2 { 0x4bf0b99a9f0dca12,
c0: Fq::from_repr(FqRepr([0x8e9a7adaf6eb0eb9, 0xcb207e6b3341eaba, 0xd70b0c7b481d23ff, 0xf4ef57d604b6bca2, 0x65309427b3d5d090, 0x14c715d5553f01d2])).unwrap(), 0x3b88899a42a6318f,
c1: Fq::from_repr(FqRepr([0xfdb032e7d9079a94, 0x35a2809d15468d83, 0xfe4b23317e0796d5, 0xd62fa51334f560fa, 0x9ad265eb46e01984, 0x1303f3465112c8bc])).unwrap() 0x986a4a62fa82a49d,
0x13ce433fa26027f5,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x66323bf80b58b9b9,
0xa1379b6facf6e596,
0x402aef1fb797e32f,
0x2236f55246d0d44d,
0x4c8c1800eb104566,
0x11d6e20e986c2085,
])).unwrap(),
}); });
assert_eq!(
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x8e9a7adaf6eb0eb9,
0xcb207e6b3341eaba,
0xd70b0c7b481d23ff,
0xf4ef57d604b6bca2,
0x65309427b3d5d090,
0x14c715d5553f01d2
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xfdb032e7d9079a94,
0x35a2809d15468d83,
0xfe4b23317e0796d5,
0xd62fa51334f560fa,
0x9ad265eb46e01984,
0x1303f3465112c8bc
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_subtraction() { fn test_fq2_subtraction() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() 0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
])).unwrap(),
}; };
a.sub_assign(&Fq2 { a.sub_assign(&Fq2 {
c0: Fq::from_repr(FqRepr([0x619a02d78dc70ef2, 0xb93adfc9119e33e8, 0x4bf0b99a9f0dca12, 0x3b88899a42a6318f, 0x986a4a62fa82a49d, 0x13ce433fa26027f5])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x66323bf80b58b9b9, 0xa1379b6facf6e596, 0x402aef1fb797e32f, 0x2236f55246d0d44d, 0x4c8c1800eb104566, 0x11d6e20e986c2085])).unwrap() 0x619a02d78dc70ef2,
}); 0xb93adfc9119e33e8,
assert_eq!(a, Fq2 { 0x4bf0b99a9f0dca12,
c0: Fq::from_repr(FqRepr([0x8565752bdb5c9b80, 0x7756bed7c15982e9, 0xa65a6be700b285fe, 0xe255902672ef6c43, 0x7f77a718021c342d, 0x72ba14049fe9881])).unwrap(), 0x3b88899a42a6318f,
c1: Fq::from_repr(FqRepr([0xeb4abaf7c255d1cd, 0x11df49bc6cacc256, 0xe52617930588c69a, 0xf63905f39ad8cb1f, 0x4cd5dd9fb40b3b8f, 0x957411359ba6e4c])).unwrap() 0x986a4a62fa82a49d,
0x13ce433fa26027f5,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x66323bf80b58b9b9,
0xa1379b6facf6e596,
0x402aef1fb797e32f,
0x2236f55246d0d44d,
0x4c8c1800eb104566,
0x11d6e20e986c2085,
])).unwrap(),
}); });
assert_eq!(
a,
Fq2 {
c0: Fq::from_repr(FqRepr([
0x8565752bdb5c9b80,
0x7756bed7c15982e9,
0xa65a6be700b285fe,
0xe255902672ef6c43,
0x7f77a718021c342d,
0x72ba14049fe9881
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xeb4abaf7c255d1cd,
0x11df49bc6cacc256,
0xe52617930588c69a,
0xf63905f39ad8cb1f,
0x4cd5dd9fb40b3b8f,
0x957411359ba6e4c
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_negation() { fn test_fq2_negation() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() 0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
])).unwrap(),
}; };
a.negate(); a.negate();
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x8cfe87fc96dbaae4, 0xcc6615c8fb0492d, 0xdc167fc04da19c37, 0xab107d49317487ab, 0x7e555df189f880e3, 0x19083f5486a10cbd])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x228109103250c9d0, 0x8a411ad149045812, 0xa9109e8f3041427e, 0xb07e9bc405608611, 0xfcd559cbe77bd8b8, 0x18d400b280d93e62])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x8cfe87fc96dbaae4,
0xcc6615c8fb0492d,
0xdc167fc04da19c37,
0xab107d49317487ab,
0x7e555df189f880e3,
0x19083f5486a10cbd
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x228109103250c9d0,
0x8a411ad149045812,
0xa9109e8f3041427e,
0xb07e9bc405608611,
0xfcd559cbe77bd8b8,
0x18d400b280d93e62
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_doubling() { fn test_fq2_doubling() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() 0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
])).unwrap(),
}; };
a.double(); a.double();
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x5a00f006d247ff8e, 0x23cb3d4443476da4, 0x1634a5c1521eb3da, 0x72cd9c7784211627, 0x998c938972a657e7, 0x1f1a52b65bdb3b9])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x2efbeddf9b5dc1b6, 0x28d5ca5ad09f4fdb, 0x7c4068238cdf674b, 0x67f15f81dc49195b, 0x9c8c9bd4b79fa83d, 0x25a226f714d506e])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x5a00f006d247ff8e,
0x23cb3d4443476da4,
0x1634a5c1521eb3da,
0x72cd9c7784211627,
0x998c938972a657e7,
0x1f1a52b65bdb3b9
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x2efbeddf9b5dc1b6,
0x28d5ca5ad09f4fdb,
0x7c4068238cdf674b,
0x67f15f81dc49195b,
0x9c8c9bd4b79fa83d,
0x25a226f714d506e
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_frobenius_map() { fn test_fq2_frobenius_map() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
let mut a = Fq2 { let mut a = Fq2 {
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() 0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc,
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837,
])).unwrap(),
}; };
a.frobenius_map(0); a.frobenius_map(0);
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837
])).unwrap(),
}
);
a.frobenius_map(1); a.frobenius_map(1);
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x228109103250c9d0, 0x8a411ad149045812, 0xa9109e8f3041427e, 0xb07e9bc405608611, 0xfcd559cbe77bd8b8, 0x18d400b280d93e62])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x228109103250c9d0,
0x8a411ad149045812,
0xa9109e8f3041427e,
0xb07e9bc405608611,
0xfcd559cbe77bd8b8,
0x18d400b280d93e62
])).unwrap(),
}
);
a.frobenius_map(1); a.frobenius_map(1);
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837
])).unwrap(),
}
);
a.frobenius_map(2); a.frobenius_map(2);
assert_eq!(a, Fq2 { assert_eq!(
c0: Fq::from_repr(FqRepr([0x2d0078036923ffc7, 0x11e59ea221a3b6d2, 0x8b1a52e0a90f59ed, 0xb966ce3bc2108b13, 0xccc649c4b9532bf3, 0xf8d295b2ded9dc])).unwrap(), a,
c1: Fq::from_repr(FqRepr([0x977df6efcdaee0db, 0x946ae52d684fa7ed, 0xbe203411c66fb3a5, 0xb3f8afc0ee248cad, 0x4e464dea5bcfd41e, 0x12d1137b8a6a837])).unwrap() Fq2 {
}); c0: Fq::from_repr(FqRepr([
0x2d0078036923ffc7,
0x11e59ea221a3b6d2,
0x8b1a52e0a90f59ed,
0xb966ce3bc2108b13,
0xccc649c4b9532bf3,
0xf8d295b2ded9dc
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0x977df6efcdaee0db,
0x946ae52d684fa7ed,
0xbe203411c66fb3a5,
0xb3f8afc0ee248cad,
0x4e464dea5bcfd41e,
0x12d1137b8a6a837
])).unwrap(),
}
);
} }
#[test] #[test]
fn test_fq2_sqrt() { fn test_fq2_sqrt() {
use ::PrimeField; use PrimeField;
use super::fq::{FqRepr}; use super::fq::FqRepr;
assert_eq!( assert_eq!(
Fq2 { Fq2 {
c0: Fq::from_repr(FqRepr([0x476b4c309720e227, 0x34c2d04faffdab6, 0xa57e6fc1bab51fd9, 0xdb4a116b5bf74aa1, 0x1e58b2159dfe10e2, 0x7ca7da1f13606ac])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0xfa8de88b7516d2c3, 0x371a75ed14f41629, 0x4cec2dca577a3eb6, 0x212611bca4e99121, 0x8ee5394d77afb3d, 0xec92336650e49d5])).unwrap() 0x476b4c309720e227,
}.sqrt().unwrap(), 0x34c2d04faffdab6,
0xa57e6fc1bab51fd9,
0xdb4a116b5bf74aa1,
0x1e58b2159dfe10e2,
0x7ca7da1f13606ac
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xfa8de88b7516d2c3,
0x371a75ed14f41629,
0x4cec2dca577a3eb6,
0x212611bca4e99121,
0x8ee5394d77afb3d,
0xec92336650e49d5
])).unwrap(),
}.sqrt()
.unwrap(),
Fq2 { Fq2 {
c0: Fq::from_repr(FqRepr([0x40b299b2704258c5, 0x6ef7de92e8c68b63, 0x6d2ddbe552203e82, 0x8d7f1f723d02c1d3, 0x881b3e01b611c070, 0x10f6963bbad2ebc5])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::from_repr(FqRepr([0xc099534fc209e752, 0x7670594665676447, 0x28a20faed211efe7, 0x6b852aeaf2afcb1b, 0xa4c93b08105d71a9, 0x8d7cfff94216330])).unwrap() 0x40b299b2704258c5,
0x6ef7de92e8c68b63,
0x6d2ddbe552203e82,
0x8d7f1f723d02c1d3,
0x881b3e01b611c070,
0x10f6963bbad2ebc5
])).unwrap(),
c1: Fq::from_repr(FqRepr([
0xc099534fc209e752,
0x7670594665676447,
0x28a20faed211efe7,
0x6b852aeaf2afcb1b,
0xa4c93b08105d71a9,
0x8d7cfff94216330
])).unwrap(),
} }
); );
assert_eq!( assert_eq!(
Fq2 { Fq2 {
c0: Fq::from_repr(FqRepr([0xb9f78429d1517a6b, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a])).unwrap(), c0: Fq::from_repr(FqRepr([
c1: Fq::zero() 0xb9f78429d1517a6b,
}.sqrt().unwrap(), 0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a
])).unwrap(),
c1: Fq::zero(),
}.sqrt()
.unwrap(),
Fq2 { Fq2 {
c0: Fq::zero(), c0: Fq::zero(),
c1: Fq::from_repr(FqRepr([0xb9fefffffd4357a3, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a])).unwrap() c1: Fq::from_repr(FqRepr([
0xb9fefffffd4357a3,
0x1eabfffeb153ffff,
0x6730d2a0f6b0f624,
0x64774b84f38512bf,
0x4b1ba7b6434bacd7,
0x1a0111ea397fe69a
])).unwrap(),
} }
); );
} }
#[test] #[test]
fn test_fq2_legendre() { fn test_fq2_legendre() {
use ::LegendreSymbol::*; use LegendreSymbol::*;
assert_eq!(Zero, Fq2::zero().legendre()); assert_eq!(Zero, Fq2::zero().legendre());
// i^2 = -1 // i^2 = -1
@@ -450,7 +885,7 @@ fn test_fq2_mul_nonresidue() {
let nqr = Fq2 { let nqr = Fq2 {
c0: Fq::one(), c0: Fq::one(),
c1: Fq::one() c1: Fq::one(),
}; };
for _ in 0..1000 { for _ in 0..1000 {
@@ -465,7 +900,7 @@ fn test_fq2_mul_nonresidue() {
#[test] #[test]
fn fq2_field_tests() { fn fq2_field_tests() {
use ::PrimeField; use PrimeField;
::tests::field::random_field_tests::<Fq2>(); ::tests::field::random_field_tests::<Fq2>();
::tests::field::random_sqrt_tests::<Fq2>(); ::tests::field::random_sqrt_tests::<Fq2>();

View File

@@ -1,5 +1,5 @@
use rand::{Rng, Rand}; use rand::{Rand, Rng};
use ::{Field}; use Field;
use super::fq2::Fq2; use super::fq2::Fq2;
use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2}; use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
@@ -8,11 +8,10 @@ use super::fq::{FROBENIUS_COEFF_FQ6_C1, FROBENIUS_COEFF_FQ6_C2};
pub struct Fq6 { pub struct Fq6 {
pub c0: Fq2, pub c0: Fq2,
pub c1: Fq2, pub c1: Fq2,
pub c2: Fq2 pub c2: Fq2,
} }
impl ::std::fmt::Display for Fq6 impl ::std::fmt::Display for Fq6 {
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fq6({} + {} * v, {} * v^2)", self.c0, self.c1, self.c2) write!(f, "Fq6({} + {} * v, {} * v^2)", self.c0, self.c1, self.c2)
} }
@@ -23,7 +22,7 @@ impl Rand for Fq6 {
Fq6 { Fq6 {
c0: rng.gen(), c0: rng.gen(),
c1: rng.gen(), c1: rng.gen(),
c2: rng.gen() c2: rng.gen(),
} }
} }
} }
@@ -38,8 +37,7 @@ impl Fq6 {
self.c0.mul_by_nonresidue(); self.c0.mul_by_nonresidue();
} }
pub fn mul_by_1(&mut self, c1: &Fq2) pub fn mul_by_1(&mut self, c1: &Fq2) {
{
let mut b_b = self.c1; let mut b_b = self.c1;
b_b.mul_assign(c1); b_b.mul_assign(c1);
@@ -67,8 +65,7 @@ impl Fq6 {
self.c2 = b_b; self.c2 = b_b;
} }
pub fn mul_by_01(&mut self, c0: &Fq2, c1: &Fq2) pub fn mul_by_01(&mut self, c0: &Fq2, c1: &Fq2) {
{
let mut a_a = self.c0; let mut a_a = self.c0;
let mut b_b = self.c1; let mut b_b = self.c1;
a_a.mul_assign(c0); a_a.mul_assign(c0);
@@ -112,13 +109,12 @@ impl Fq6 {
} }
} }
impl Field for Fq6 impl Field for Fq6 {
{
fn zero() -> Self { fn zero() -> Self {
Fq6 { Fq6 {
c0: Fq2::zero(), c0: Fq2::zero(),
c1: Fq2::zero(), c1: Fq2::zero(),
c2: Fq2::zero() c2: Fq2::zero(),
} }
} }
@@ -126,7 +122,7 @@ impl Field for Fq6
Fq6 { Fq6 {
c0: Fq2::one(), c0: Fq2::one(),
c1: Fq2::zero(), c1: Fq2::zero(),
c2: Fq2::zero() c2: Fq2::zero(),
} }
} }
@@ -158,8 +154,7 @@ impl Field for Fq6
self.c2.sub_assign(&other.c2); self.c2.sub_assign(&other.c2);
} }
fn frobenius_map(&mut self, power: usize) fn frobenius_map(&mut self, power: usize) {
{
self.c0.frobenius_map(power); self.c0.frobenius_map(power);
self.c1.frobenius_map(power); self.c1.frobenius_map(power);
self.c2.frobenius_map(power); self.c2.frobenius_map(power);
@@ -293,15 +288,15 @@ impl Field for Fq6
let mut tmp = Fq6 { let mut tmp = Fq6 {
c0: t, c0: t,
c1: t, c1: t,
c2: t c2: t,
}; };
tmp.c0.mul_assign(&c0); tmp.c0.mul_assign(&c0);
tmp.c1.mul_assign(&c1); tmp.c1.mul_assign(&c1);
tmp.c2.mul_assign(&c2); tmp.c2.mul_assign(&c2);
Some(tmp) Some(tmp)
}, }
None => None None => None,
} }
} }
} }
@@ -316,7 +311,7 @@ fn test_fq6_mul_nonresidue() {
let nqr = Fq6 { let nqr = Fq6 {
c0: Fq2::zero(), c0: Fq2::zero(),
c1: Fq2::one(), c1: Fq2::one(),
c2: Fq2::zero() c2: Fq2::zero(),
}; };
for _ in 0..1000 { for _ in 0..1000 {
@@ -342,7 +337,7 @@ fn test_fq6_mul_by_1() {
b.mul_assign(&Fq6 { b.mul_assign(&Fq6 {
c0: Fq2::zero(), c0: Fq2::zero(),
c1: c1, c1: c1,
c2: Fq2::zero() c2: Fq2::zero(),
}); });
assert_eq!(a, b); assert_eq!(a, b);
@@ -363,7 +358,7 @@ fn test_fq6_mul_by_01() {
b.mul_assign(&Fq6 { b.mul_assign(&Fq6 {
c0: c0, c0: c0,
c1: c1, c1: c1,
c2: Fq2::zero() c2: Fq2::zero(),
}); });
assert_eq!(a, b); assert_eq!(a, b);
@@ -372,7 +367,7 @@ fn test_fq6_mul_by_01() {
#[test] #[test]
fn fq6_field_tests() { fn fq6_field_tests() {
use ::PrimeField; use PrimeField;
::tests::field::random_field_tests::<Fq6>(); ::tests::field::random_field_tests::<Fq6>();
::tests::field::random_frobenius_tests::<Fq6, _>(super::fq::Fq::char(), 13); ::tests::field::random_frobenius_tests::<Fq6, _>(super::fq::Fq::char(), 13);

View File

@@ -1,8 +1,13 @@
use ::{Field, PrimeField, SqrtField, PrimeFieldRepr, PrimeFieldDecodingError}; use {Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField};
use ::LegendreSymbol::*; use LegendreSymbol::*;
// r = 52435875175126190479447740508185965837690552500527637822603658699938581184513 // r = 52435875175126190479447740508185965837690552500527637822603658699938581184513
const MODULUS: FrRepr = FrRepr([0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48]); const MODULUS: FrRepr = FrRepr([
0xffffffff00000001,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
// The number of bits needed to represent the modulus. // The number of bits needed to represent the modulus.
const MODULUS_BITS: u32 = 255; const MODULUS_BITS: u32 = 255;
@@ -12,22 +17,42 @@ const MODULUS_BITS: u32 = 255;
const REPR_SHAVE_BITS: u32 = 1; const REPR_SHAVE_BITS: u32 = 1;
// R = 2**256 % r // R = 2**256 % r
const R: FrRepr = FrRepr([0x1fffffffe, 0x5884b7fa00034802, 0x998c4fefecbc4ff5, 0x1824b159acc5056f]); const R: FrRepr = FrRepr([
0x1fffffffe,
0x5884b7fa00034802,
0x998c4fefecbc4ff5,
0x1824b159acc5056f,
]);
// R2 = R^2 % r // R2 = R^2 % r
const R2: FrRepr = FrRepr([0xc999e990f3f29c6d, 0x2b6cedcb87925c23, 0x5d314967254398f, 0x748d9d99f59ff11]); const R2: FrRepr = FrRepr([
0xc999e990f3f29c6d,
0x2b6cedcb87925c23,
0x5d314967254398f,
0x748d9d99f59ff11,
]);
// INV = -(r^{-1} mod 2^64) mod 2^64 // INV = -(r^{-1} mod 2^64) mod 2^64
const INV: u64 = 0xfffffffeffffffff; const INV: u64 = 0xfffffffeffffffff;
// GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue) // GENERATOR = 7 (multiplicative generator of r-1 order, that is also quadratic nonresidue)
const GENERATOR: FrRepr = FrRepr([0xefffffff1, 0x17e363d300189c0f, 0xff9c57876f8457b0, 0x351332208fc5a8c4]); const GENERATOR: FrRepr = FrRepr([
0xefffffff1,
0x17e363d300189c0f,
0xff9c57876f8457b0,
0x351332208fc5a8c4,
]);
// 2^s * t = MODULUS - 1 with t odd // 2^s * t = MODULUS - 1 with t odd
const S: u32 = 32; const S: u32 = 32;
// 2^s root of unity computed by GENERATOR^t // 2^s root of unity computed by GENERATOR^t
const ROOT_OF_UNITY: FrRepr = FrRepr([0xb9b58d8c5f0e466a, 0x5b1b4c801819d7ec, 0xaf53ae352a31e64, 0x5bf3adda19e9b27b]); const ROOT_OF_UNITY: FrRepr = FrRepr([
0xb9b58d8c5f0e466a,
0x5b1b4c801819d7ec,
0xaf53ae352a31e64,
0x5bf3adda19e9b27b,
]);
#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
pub struct FrRepr(pub [u64; 4]); pub struct FrRepr(pub [u64; 4]);
@@ -39,8 +64,7 @@ impl ::rand::Rand for FrRepr {
} }
} }
impl ::std::fmt::Display for FrRepr impl ::std::fmt::Display for FrRepr {
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
try!(write!(f, "0x")); try!(write!(f, "0x"));
for i in self.0.iter().rev() { for i in self.0.iter().rev() {
@@ -79,9 +103,9 @@ impl Ord for FrRepr {
fn cmp(&self, other: &FrRepr) -> ::std::cmp::Ordering { fn cmp(&self, other: &FrRepr) -> ::std::cmp::Ordering {
for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) { for (a, b) in self.0.iter().rev().zip(other.0.iter().rev()) {
if a < b { if a < b {
return ::std::cmp::Ordering::Less return ::std::cmp::Ordering::Less;
} else if a > b { } else if a > b {
return ::std::cmp::Ordering::Greater return ::std::cmp::Ordering::Greater;
} }
} }
@@ -222,8 +246,7 @@ impl PrimeFieldRepr for FrRepr {
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub struct Fr(FrRepr); pub struct Fr(FrRepr);
impl ::std::fmt::Display for Fr impl ::std::fmt::Display for Fr {
{
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "Fr({})", self.into_repr()) write!(f, "Fr({})", self.into_repr())
} }
@@ -238,7 +261,7 @@ impl ::rand::Rand for Fr {
tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS; tmp.0.as_mut()[3] &= 0xffffffffffffffff >> REPR_SHAVE_BITS;
if tmp.is_valid() { if tmp.is_valid() {
return tmp return tmp;
} }
} }
} }
@@ -266,9 +289,16 @@ impl PrimeField for Fr {
fn into_repr(&self) -> FrRepr { fn into_repr(&self) -> FrRepr {
let mut r = *self; let mut r = *self;
r.mont_reduce((self.0).0[0], (self.0).0[1], r.mont_reduce(
(self.0).0[2], (self.0).0[3], (self.0).0[0],
0, 0, 0, 0); (self.0).0[1],
(self.0).0[2],
(self.0).0[3],
0,
0,
0,
0,
);
r.0 r.0
} }
@@ -405,8 +435,7 @@ impl Field for Fr {
} }
#[inline] #[inline]
fn mul_assign(&mut self, other: &Fr) fn mul_assign(&mut self, other: &Fr) {
{
let mut carry = 0; let mut carry = 0;
let r0 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry); let r0 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[0], &mut carry);
let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry); let r1 = ::mac_with_carry(0, (self.0).0[0], (other.0).0[1], &mut carry);
@@ -435,8 +464,7 @@ impl Field for Fr {
} }
#[inline] #[inline]
fn square(&mut self) fn square(&mut self) {
{
let mut carry = 0; let mut carry = 0;
let r1 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry); let r1 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[1], &mut carry);
let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry); let r2 = ::mac_with_carry(0, (self.0).0[0], (self.0).0[2], &mut carry);
@@ -498,9 +526,8 @@ impl Fr {
mut r4: u64, mut r4: u64,
mut r5: u64, mut r5: u64,
mut r6: u64, mut r6: u64,
mut r7: u64 mut r7: u64,
) ) {
{
// The Montgomery reduction here is based on Algorithm 14.32 in // The Montgomery reduction here is based on Algorithm 14.32 in
// Handbook of Applied Cryptography // Handbook of Applied Cryptography
// <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>. // <http://cacr.uwaterloo.ca/hac/about/chap14.pdf>.
@@ -545,13 +572,21 @@ impl Fr {
} }
impl SqrtField for Fr { impl SqrtField for Fr {
fn legendre(&self) -> ::LegendreSymbol { fn legendre(&self) -> ::LegendreSymbol {
// s = self^((r - 1) // 2) // s = self^((r - 1) // 2)
let s = self.pow([0x7fffffff80000000, 0xa9ded2017fff2dff, 0x199cec0404d0ec02, 0x39f6d3a994cebea4]); let s = self.pow([
if s == Self::zero() { Zero } 0x7fffffff80000000,
else if s == Self::one() { QuadraticResidue } 0xa9ded2017fff2dff,
else { QuadraticNonResidue } 0x199cec0404d0ec02,
0x39f6d3a994cebea4,
]);
if s == Self::zero() {
Zero
} else if s == Self::one() {
QuadraticResidue
} else {
QuadraticNonResidue
}
} }
fn sqrt(&self) -> Option<Self> { fn sqrt(&self) -> Option<Self> {
@@ -563,9 +598,19 @@ impl SqrtField for Fr {
QuadraticResidue => { QuadraticResidue => {
let mut c = Fr(ROOT_OF_UNITY); let mut c = Fr(ROOT_OF_UNITY);
// r = self^((t + 1) // 2) // r = self^((t + 1) // 2)
let mut r = self.pow([0x7fff2dff80000000, 0x4d0ec02a9ded201, 0x94cebea4199cec04, 0x39f6d3a9]); let mut r = self.pow([
0x7fff2dff80000000,
0x4d0ec02a9ded201,
0x94cebea4199cec04,
0x39f6d3a9,
]);
// t = self^t // t = self^t
let mut t = self.pow([0xfffe5bfeffffffff, 0x9a1d80553bda402, 0x299d7d483339d808, 0x73eda753]); let mut t = self.pow([
0xfffe5bfeffffffff,
0x9a1d80553bda402,
0x299d7d483339d808,
0x73eda753,
]);
let mut m = S; let mut m = S;
while t != Self::one() { while t != Self::one() {
@@ -598,7 +643,7 @@ impl SqrtField for Fr {
} }
#[cfg(test)] #[cfg(test)]
use rand::{SeedableRng, XorShiftRng, Rand}; use rand::{Rand, SeedableRng, XorShiftRng};
#[test] #[test]
fn test_fr_repr_ordering() { fn test_fr_repr_ordering() {
@@ -612,12 +657,30 @@ fn test_fr_repr_ordering() {
assert!(b > a); assert!(b > a);
} }
assert_equality(FrRepr([9999, 9999, 9999, 9999]), FrRepr([9999, 9999, 9999, 9999])); assert_equality(
assert_equality(FrRepr([9999, 9998, 9999, 9999]), FrRepr([9999, 9998, 9999, 9999])); FrRepr([9999, 9999, 9999, 9999]),
assert_equality(FrRepr([9999, 9999, 9999, 9997]), FrRepr([9999, 9999, 9999, 9997])); FrRepr([9999, 9999, 9999, 9999]),
assert_lt(FrRepr([9999, 9997, 9999, 9998]), FrRepr([9999, 9997, 9999, 9999])); );
assert_lt(FrRepr([9999, 9997, 9998, 9999]), FrRepr([9999, 9997, 9999, 9999])); assert_equality(
assert_lt(FrRepr([9, 9999, 9999, 9997]), FrRepr([9999, 9999, 9999, 9997])); FrRepr([9999, 9998, 9999, 9999]),
FrRepr([9999, 9998, 9999, 9999]),
);
assert_equality(
FrRepr([9999, 9999, 9999, 9997]),
FrRepr([9999, 9999, 9999, 9997]),
);
assert_lt(
FrRepr([9999, 9997, 9999, 9998]),
FrRepr([9999, 9997, 9999, 9999]),
);
assert_lt(
FrRepr([9999, 9997, 9998, 9999]),
FrRepr([9999, 9997, 9999, 9999]),
);
assert_lt(
FrRepr([9, 9999, 9999, 9997]),
FrRepr([9999, 9999, 9999, 9997]),
);
} }
#[test] #[test]
@@ -646,13 +709,34 @@ fn test_fr_repr_is_zero() {
#[test] #[test]
fn test_fr_repr_div2() { fn test_fr_repr_div2() {
let mut a = FrRepr([0xbd2920b19c972321, 0x174ed0466a3be37e, 0xd468d5e3b551f0b5, 0xcb67c072733beefc]); let mut a = FrRepr([
0xbd2920b19c972321,
0x174ed0466a3be37e,
0xd468d5e3b551f0b5,
0xcb67c072733beefc,
]);
a.div2(); a.div2();
assert_eq!(a, FrRepr([0x5e949058ce4b9190, 0x8ba76823351df1bf, 0x6a346af1daa8f85a, 0x65b3e039399df77e])); assert_eq!(
a,
FrRepr([
0x5e949058ce4b9190,
0x8ba76823351df1bf,
0x6a346af1daa8f85a,
0x65b3e039399df77e
])
);
for _ in 0..10 { for _ in 0..10 {
a.div2(); a.div2();
} }
assert_eq!(a, FrRepr([0x6fd7a524163392e4, 0x16a2e9da08cd477c, 0xdf9a8d1abc76aa3e, 0x196cf80e4e677d])); assert_eq!(
a,
FrRepr([
0x6fd7a524163392e4,
0x16a2e9da08cd477c,
0xdf9a8d1abc76aa3e,
0x196cf80e4e677d
])
);
for _ in 0..200 { for _ in 0..200 {
a.div2(); a.div2();
} }
@@ -671,32 +755,46 @@ fn test_fr_repr_div2() {
#[test] #[test]
fn test_fr_repr_shr() { fn test_fr_repr_shr() {
let mut a = FrRepr([0xb33fbaec482a283f, 0x997de0d3a88cb3df, 0x9af62d2a9a0e5525, 0x36003ab08de70da1]); let mut a = FrRepr([
0xb33fbaec482a283f,
0x997de0d3a88cb3df,
0x9af62d2a9a0e5525,
0x36003ab08de70da1,
]);
a.shr(0); a.shr(0);
assert_eq!( assert_eq!(
a, a,
FrRepr([0xb33fbaec482a283f, 0x997de0d3a88cb3df, 0x9af62d2a9a0e5525, 0x36003ab08de70da1]) FrRepr([
0xb33fbaec482a283f,
0x997de0d3a88cb3df,
0x9af62d2a9a0e5525,
0x36003ab08de70da1
])
); );
a.shr(1); a.shr(1);
assert_eq!( assert_eq!(
a, a,
FrRepr([0xd99fdd762415141f, 0xccbef069d44659ef, 0xcd7b16954d072a92, 0x1b001d5846f386d0]) FrRepr([
0xd99fdd762415141f,
0xccbef069d44659ef,
0xcd7b16954d072a92,
0x1b001d5846f386d0
])
); );
a.shr(50); a.shr(50);
assert_eq!( assert_eq!(
a, a,
FrRepr([0xbc1a7511967bf667, 0xc5a55341caa4b32f, 0x75611bce1b4335e, 0x6c0]) FrRepr([
0xbc1a7511967bf667,
0xc5a55341caa4b32f,
0x75611bce1b4335e,
0x6c0
])
); );
a.shr(130); a.shr(130);
assert_eq!( assert_eq!(a, FrRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0]));
a,
FrRepr([0x1d5846f386d0cd7, 0x1b0, 0x0, 0x0])
);
a.shr(64); a.shr(64);
assert_eq!( assert_eq!(a, FrRepr([0x1b0, 0x0, 0x0, 0x0]));
a,
FrRepr([0x1b0, 0x0, 0x0, 0x0])
);
} }
#[test] #[test]
@@ -738,9 +836,27 @@ fn test_fr_repr_num_bits() {
fn test_fr_repr_sub_noborrow() { fn test_fr_repr_sub_noborrow() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let mut t = FrRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495]); let mut t = FrRepr([
t.sub_noborrow(&FrRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf])); 0x8e62a7e85264e2c3,
assert!(t == FrRepr([0xb813415048991c1f, 0x10ad07ae88725d92, 0x5a7b851271759961, 0x36850eedd30c39c5])); 0xb23d34c1941d3ca,
0x5976930b7502dd15,
0x600f3fb517bf5495,
]);
t.sub_noborrow(&FrRepr([
0xd64f669809cbc6a4,
0xfa76cb9d90cf7637,
0xfefb0df9038d43b3,
0x298a30c744b31acf,
]));
assert!(
t
== FrRepr([
0xb813415048991c1f,
0x10ad07ae88725d92,
0x5a7b851271759961,
0x36850eedd30c39c5
])
);
for _ in 0..1000 { for _ in 0..1000 {
let mut a = FrRepr::rand(&mut rng); let mut a = FrRepr::rand(&mut rng);
@@ -769,9 +885,27 @@ fn test_fr_repr_sub_noborrow() {
} }
// Subtracting r+1 from r should produce -1 (mod 2**256) // Subtracting r+1 from r should produce -1 (mod 2**256)
let mut qplusone = FrRepr([0xffffffff00000001, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48]); let mut qplusone = FrRepr([
qplusone.sub_noborrow(&FrRepr([0xffffffff00000002, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48])); 0xffffffff00000001,
assert_eq!(qplusone, FrRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])); 0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]);
qplusone.sub_noborrow(&FrRepr([
0xffffffff00000002,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]));
assert_eq!(
qplusone,
FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])
);
} }
#[test] #[test]
@@ -779,9 +913,19 @@ fn test_fr_legendre() {
assert_eq!(QuadraticResidue, Fr::one().legendre()); assert_eq!(QuadraticResidue, Fr::one().legendre());
assert_eq!(Zero, Fr::zero().legendre()); assert_eq!(Zero, Fr::zero().legendre());
let e = FrRepr([0x0dbc5349cd5664da, 0x8ac5b6296e3ae29d, 0x127cb819feceaa3b, 0x3a6b21fb03867191]); let e = FrRepr([
0x0dbc5349cd5664da,
0x8ac5b6296e3ae29d,
0x127cb819feceaa3b,
0x3a6b21fb03867191,
]);
assert_eq!(QuadraticResidue, Fr::from_repr(e).unwrap().legendre()); assert_eq!(QuadraticResidue, Fr::from_repr(e).unwrap().legendre());
let e = FrRepr([0x96341aefd047c045, 0x9b5f4254500a4d65, 0x1ee08223b68ac240, 0x31d9cd545c0ec7c6]); let e = FrRepr([
0x96341aefd047c045,
0x9b5f4254500a4d65,
0x1ee08223b68ac240,
0x31d9cd545c0ec7c6,
]);
assert_eq!(QuadraticNonResidue, Fr::from_repr(e).unwrap().legendre()); assert_eq!(QuadraticNonResidue, Fr::from_repr(e).unwrap().legendre());
} }
@@ -789,9 +933,27 @@ fn test_fr_legendre() {
fn test_fr_repr_add_nocarry() { fn test_fr_repr_add_nocarry() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let mut t = FrRepr([0xd64f669809cbc6a4, 0xfa76cb9d90cf7637, 0xfefb0df9038d43b3, 0x298a30c744b31acf]); let mut t = FrRepr([
t.add_nocarry(&FrRepr([0x8e62a7e85264e2c3, 0xb23d34c1941d3ca, 0x5976930b7502dd15, 0x600f3fb517bf5495])); 0xd64f669809cbc6a4,
assert_eq!(t, FrRepr([0x64b20e805c30a967, 0x59a9ee9aa114a02, 0x5871a104789020c9, 0x8999707c5c726f65])); 0xfa76cb9d90cf7637,
0xfefb0df9038d43b3,
0x298a30c744b31acf,
]);
t.add_nocarry(&FrRepr([
0x8e62a7e85264e2c3,
0xb23d34c1941d3ca,
0x5976930b7502dd15,
0x600f3fb517bf5495,
]));
assert_eq!(
t,
FrRepr([
0x64b20e805c30a967,
0x59a9ee9aa114a02,
0x5871a104789020c9,
0x8999707c5c726f65
])
);
// Test for the associativity of addition. // Test for the associativity of addition.
for _ in 0..1000 { for _ in 0..1000 {
@@ -836,7 +998,12 @@ fn test_fr_repr_add_nocarry() {
} }
// Adding 1 to (2^256 - 1) should produce zero // Adding 1 to (2^256 - 1) should produce zero
let mut x = FrRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff]); let mut x = FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
]);
x.add_nocarry(&FrRepr::from(1)); x.add_nocarry(&FrRepr::from(1));
assert!(x.is_zero()); assert!(x.is_zero());
} }
@@ -848,8 +1015,20 @@ fn test_fr_is_valid() {
a.0.sub_noborrow(&FrRepr::from(1)); a.0.sub_noborrow(&FrRepr::from(1));
assert!(a.is_valid()); assert!(a.is_valid());
assert!(Fr(FrRepr::from(0)).is_valid()); assert!(Fr(FrRepr::from(0)).is_valid());
assert!(Fr(FrRepr([0xffffffff00000000, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48])).is_valid()); assert!(
assert!(!Fr(FrRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])).is_valid()); Fr(FrRepr([
0xffffffff00000000,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
])).is_valid()
);
assert!(!Fr(FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])).is_valid());
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@@ -863,25 +1042,82 @@ fn test_fr_is_valid() {
fn test_fr_add_assign() { fn test_fr_add_assign() {
{ {
// Random number // Random number
let mut tmp = Fr(FrRepr([0x437ce7616d580765, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca])); let mut tmp = Fr(FrRepr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca,
]));
assert!(tmp.is_valid()); assert!(tmp.is_valid());
// Test that adding zero has no effect. // Test that adding zero has no effect.
tmp.add_assign(&Fr(FrRepr::from(0))); tmp.add_assign(&Fr(FrRepr::from(0)));
assert_eq!(tmp, Fr(FrRepr([0x437ce7616d580765, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca]))); assert_eq!(
tmp,
Fr(FrRepr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
);
// Add one and test for the result. // Add one and test for the result.
tmp.add_assign(&Fr(FrRepr::from(1))); tmp.add_assign(&Fr(FrRepr::from(1)));
assert_eq!(tmp, Fr(FrRepr([0x437ce7616d580766, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca]))); assert_eq!(
tmp,
Fr(FrRepr([
0x437ce7616d580766,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
);
// Add another random number that exercises the reduction. // Add another random number that exercises the reduction.
tmp.add_assign(&Fr(FrRepr([0x946f435944f7dc79, 0xb55e7ee6533a9b9b, 0x1e43b84c2f6194ca, 0x58717ab525463496]))); tmp.add_assign(&Fr(FrRepr([
assert_eq!(tmp, Fr(FrRepr([0xd7ec2abbb24fe3de, 0x35cdf7ae7d0d62f7, 0xd899557c477cd0e9, 0x3371b52bc43de018]))); 0x946f435944f7dc79,
0xb55e7ee6533a9b9b,
0x1e43b84c2f6194ca,
0x58717ab525463496,
])));
assert_eq!(
tmp,
Fr(FrRepr([
0xd7ec2abbb24fe3de,
0x35cdf7ae7d0d62f7,
0xd899557c477cd0e9,
0x3371b52bc43de018
]))
);
// Add one to (r - 1) and test for the result. // Add one to (r - 1) and test for the result.
tmp = Fr(FrRepr([0xffffffff00000000, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48])); tmp = Fr(FrRepr([
0xffffffff00000000,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48,
]));
tmp.add_assign(&Fr(FrRepr::from(1))); tmp.add_assign(&Fr(FrRepr::from(1)));
assert!(tmp.0.is_zero()); assert!(tmp.0.is_zero());
// Add a random number to another one such that the result is r - 1 // Add a random number to another one such that the result is r - 1
tmp = Fr(FrRepr([0xade5adacdccb6190, 0xaa21ee0f27db3ccd, 0x2550f4704ae39086, 0x591d1902e7c5ba27])); tmp = Fr(FrRepr([
tmp.add_assign(&Fr(FrRepr([0x521a525223349e70, 0xa99bb5f3d8231f31, 0xde8e397bebe477e, 0x1ad08e5041d7c321]))); 0xade5adacdccb6190,
assert_eq!(tmp, Fr(FrRepr([0xffffffff00000000, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48]))); 0xaa21ee0f27db3ccd,
0x2550f4704ae39086,
0x591d1902e7c5ba27,
]));
tmp.add_assign(&Fr(FrRepr([
0x521a525223349e70,
0xa99bb5f3d8231f31,
0xde8e397bebe477e,
0x1ad08e5041d7c321,
])));
assert_eq!(
tmp,
Fr(FrRepr([
0xffffffff00000000,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
]))
);
// Add one to the result and test for it. // Add one to the result and test for it.
tmp.add_assign(&Fr(FrRepr::from(1))); tmp.add_assign(&Fr(FrRepr::from(1)));
assert!(tmp.0.is_zero()); assert!(tmp.0.is_zero());
@@ -915,23 +1151,72 @@ fn test_fr_add_assign() {
fn test_fr_sub_assign() { fn test_fr_sub_assign() {
{ {
// Test arbitrary subtraction that tests reduction. // Test arbitrary subtraction that tests reduction.
let mut tmp = Fr(FrRepr([0x6a68c64b6f735a2b, 0xd5f4d143fe0a1972, 0x37c17f3829267c62, 0xa2f37391f30915c])); let mut tmp = Fr(FrRepr([
tmp.sub_assign(&Fr(FrRepr([0xade5adacdccb6190, 0xaa21ee0f27db3ccd, 0x2550f4704ae39086, 0x591d1902e7c5ba27]))); 0x6a68c64b6f735a2b,
assert_eq!(tmp, Fr(FrRepr([0xbc83189d92a7f89c, 0x7f908737d62d38a3, 0x45aa62cfe7e4c3e1, 0x24ffc5896108547d]))); 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. // Test the opposite subtraction which doesn't test reduction.
tmp = Fr(FrRepr([0xade5adacdccb6190, 0xaa21ee0f27db3ccd, 0x2550f4704ae39086, 0x591d1902e7c5ba27])); tmp = Fr(FrRepr([
tmp.sub_assign(&Fr(FrRepr([0x6a68c64b6f735a2b, 0xd5f4d143fe0a1972, 0x37c17f3829267c62, 0xa2f37391f30915c]))); 0xade5adacdccb6190,
assert_eq!(tmp, Fr(FrRepr([0x437ce7616d580765, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca]))); 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 // Test for sensible results with zero
tmp = Fr(FrRepr::from(0)); tmp = Fr(FrRepr::from(0));
tmp.sub_assign(&Fr(FrRepr::from(0))); tmp.sub_assign(&Fr(FrRepr::from(0)));
assert!(tmp.is_zero()); assert!(tmp.is_zero());
tmp = Fr(FrRepr([0x437ce7616d580765, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca])); tmp = Fr(FrRepr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca,
]));
tmp.sub_assign(&Fr(FrRepr::from(0))); tmp.sub_assign(&Fr(FrRepr::from(0)));
assert_eq!(tmp, Fr(FrRepr([0x437ce7616d580765, 0xd42d1ccb29d1235b, 0xed8f753821bd1423, 0x4eede1c9c89528ca]))); assert_eq!(
tmp,
Fr(FrRepr([
0x437ce7616d580765,
0xd42d1ccb29d1235b,
0xed8f753821bd1423,
0x4eede1c9c89528ca
]))
);
} }
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@@ -954,9 +1239,27 @@ fn test_fr_sub_assign() {
#[test] #[test]
fn test_fr_mul_assign() { fn test_fr_mul_assign() {
let mut tmp = Fr(FrRepr([0x6b7e9b8faeefc81a, 0xe30a8463f348ba42, 0xeff3cb67a8279c9c, 0x3d303651bd7c774d])); let mut tmp = Fr(FrRepr([
tmp.mul_assign(&Fr(FrRepr([0x13ae28e3bc35ebeb, 0xa10f4488075cae2c, 0x8160e95a853c3b5d, 0x5ae3f03b561a841d]))); 0x6b7e9b8faeefc81a,
assert!(tmp == Fr(FrRepr([0x23717213ce710f71, 0xdbee1fe53a16e1af, 0xf565d3e1c2a48000, 0x4426507ee75df9d7]))); 0xe30a8463f348ba42,
0xeff3cb67a8279c9c,
0x3d303651bd7c774d,
]));
tmp.mul_assign(&Fr(FrRepr([
0x13ae28e3bc35ebeb,
0xa10f4488075cae2c,
0x8160e95a853c3b5d,
0x5ae3f03b561a841d,
])));
assert!(
tmp
== Fr(FrRepr([
0x23717213ce710f71,
0xdbee1fe53a16e1af,
0xf565d3e1c2a48000,
0x4426507ee75df9d7
]))
);
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@@ -1003,10 +1306,23 @@ fn test_fr_mul_assign() {
#[test] #[test]
fn test_fr_squaring() { fn test_fr_squaring() {
let mut a = Fr(FrRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0x73eda753299d7d47])); let mut a = Fr(FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0x73eda753299d7d47,
]));
assert!(a.is_valid()); assert!(a.is_valid());
a.square(); a.square();
assert_eq!(a, Fr::from_repr(FrRepr([0xc0d698e7bde077b8, 0xb79a310579e76ec2, 0xac1da8d0a9af4e5f, 0x13f629c49bf23e97])).unwrap()); assert_eq!(
a,
Fr::from_repr(FrRepr([
0xc0d698e7bde077b8,
0xb79a310579e76ec2,
0xac1da8d0a9af4e5f,
0x13f629c49bf23e97
])).unwrap()
);
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@@ -1135,17 +1451,39 @@ fn test_fr_sqrt() {
#[test] #[test]
fn test_fr_from_into_repr() { fn test_fr_from_into_repr() {
// r + 1 should not be in the field // r + 1 should not be in the field
assert!(Fr::from_repr(FrRepr([0xffffffff00000002, 0x53bda402fffe5bfe, 0x3339d80809a1d805, 0x73eda753299d7d48])).is_err()); assert!(
Fr::from_repr(FrRepr([
0xffffffff00000002,
0x53bda402fffe5bfe,
0x3339d80809a1d805,
0x73eda753299d7d48
])).is_err()
);
// r should not be in the field // r should not be in the field
assert!(Fr::from_repr(Fr::char()).is_err()); assert!(Fr::from_repr(Fr::char()).is_err());
// Multiply some arbitrary representations to see if the result is as expected. // Multiply some arbitrary representations to see if the result is as expected.
let a = FrRepr([0x25ebe3a3ad3c0c6a, 0x6990e39d092e817c, 0x941f900d42f5658e, 0x44f8a103b38a71e0]); let a = FrRepr([
0x25ebe3a3ad3c0c6a,
0x6990e39d092e817c,
0x941f900d42f5658e,
0x44f8a103b38a71e0,
]);
let mut a_fr = Fr::from_repr(a).unwrap(); let mut a_fr = Fr::from_repr(a).unwrap();
let b = FrRepr([0x264e9454885e2475, 0x46f7746bb0308370, 0x4683ef5347411f9, 0x58838d7f208d4492]); let b = FrRepr([
0x264e9454885e2475,
0x46f7746bb0308370,
0x4683ef5347411f9,
0x58838d7f208d4492,
]);
let b_fr = Fr::from_repr(b).unwrap(); let b_fr = Fr::from_repr(b).unwrap();
let c = FrRepr([0x48a09ab93cfc740d, 0x3a6600fbfc7a671, 0x838567017501d767, 0x7161d6da77745512]); let c = FrRepr([
0x48a09ab93cfc740d,
0x3a6600fbfc7a671,
0x838567017501d767,
0x7161d6da77745512,
]);
a_fr.mul_assign(&b_fr); a_fr.mul_assign(&b_fr);
assert_eq!(a_fr.into_repr(), c); assert_eq!(a_fr.into_repr(), c);
@@ -1169,15 +1507,39 @@ fn test_fr_from_into_repr() {
#[test] #[test]
fn test_fr_repr_display() { fn test_fr_repr_display() {
assert_eq!( assert_eq!(
format!("{}", FrRepr([0x2829c242fa826143, 0x1f32cf4dd4330917, 0x932e4e479d168cd9, 0x513c77587f563f64])), format!(
"{}",
FrRepr([
0x2829c242fa826143,
0x1f32cf4dd4330917,
0x932e4e479d168cd9,
0x513c77587f563f64
])
),
"0x513c77587f563f64932e4e479d168cd91f32cf4dd43309172829c242fa826143".to_string() "0x513c77587f563f64932e4e479d168cd91f32cf4dd43309172829c242fa826143".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", FrRepr([0x25ebe3a3ad3c0c6a, 0x6990e39d092e817c, 0x941f900d42f5658e, 0x44f8a103b38a71e0])), format!(
"{}",
FrRepr([
0x25ebe3a3ad3c0c6a,
0x6990e39d092e817c,
0x941f900d42f5658e,
0x44f8a103b38a71e0
])
),
"0x44f8a103b38a71e0941f900d42f5658e6990e39d092e817c25ebe3a3ad3c0c6a".to_string() "0x44f8a103b38a71e0941f900d42f5658e6990e39d092e817c25ebe3a3ad3c0c6a".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", FrRepr([0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff])), format!(
"{}",
FrRepr([
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff,
0xffffffffffffffff
])
),
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string() "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".to_string()
); );
assert_eq!( assert_eq!(
@@ -1189,11 +1551,27 @@ fn test_fr_repr_display() {
#[test] #[test]
fn test_fr_display() { fn test_fr_display() {
assert_eq!( assert_eq!(
format!("{}", Fr::from_repr(FrRepr([0xc3cae746a3b5ecc7, 0x185ec8eb3f5b5aee, 0x684499ffe4b9dd99, 0x7c9bba7afb68faa])).unwrap()), format!(
"{}",
Fr::from_repr(FrRepr([
0xc3cae746a3b5ecc7,
0x185ec8eb3f5b5aee,
0x684499ffe4b9dd99,
0x7c9bba7afb68faa
])).unwrap()
),
"Fr(0x07c9bba7afb68faa684499ffe4b9dd99185ec8eb3f5b5aeec3cae746a3b5ecc7)".to_string() "Fr(0x07c9bba7afb68faa684499ffe4b9dd99185ec8eb3f5b5aeec3cae746a3b5ecc7)".to_string()
); );
assert_eq!( assert_eq!(
format!("{}", Fr::from_repr(FrRepr([0x44c71298ff198106, 0xb0ad10817df79b6a, 0xd034a80a2b74132b, 0x41cf9a1336f50719])).unwrap()), format!(
"{}",
Fr::from_repr(FrRepr([
0x44c71298ff198106,
0xb0ad10817df79b6a,
0xd034a80a2b74132b,
0x41cf9a1336f50719
])).unwrap()
),
"Fr(0x41cf9a1336f50719d034a80a2b74132bb0ad10817df79b6a44c71298ff198106)".to_string() "Fr(0x41cf9a1336f50719d034a80a2b74132bb0ad10817df79b6a44c71298ff198106)".to_string()
); );
} }
@@ -1207,15 +1585,20 @@ fn test_fr_num_bits() {
#[test] #[test]
fn test_fr_root_of_unity() { fn test_fr_root_of_unity() {
assert_eq!(Fr::S, 32); assert_eq!(Fr::S, 32);
assert_eq!(Fr::multiplicative_generator(), Fr::from_repr(FrRepr::from(7)).unwrap());
assert_eq!( assert_eq!(
Fr::multiplicative_generator().pow([0xfffe5bfeffffffff, 0x9a1d80553bda402, 0x299d7d483339d808, 0x73eda753]), Fr::multiplicative_generator(),
Fr::from_repr(FrRepr::from(7)).unwrap()
);
assert_eq!(
Fr::multiplicative_generator().pow([
0xfffe5bfeffffffff,
0x9a1d80553bda402,
0x299d7d483339d808,
0x73eda753
]),
Fr::root_of_unity() Fr::root_of_unity()
); );
assert_eq!( assert_eq!(Fr::root_of_unity().pow([1 << Fr::S]), Fr::one());
Fr::root_of_unity().pow([1 << Fr::S]),
Fr::one()
);
assert!(Fr::multiplicative_generator().sqrt().is_none()); assert!(Fr::multiplicative_generator().sqrt().is_none());
} }

View File

@@ -13,9 +13,10 @@ pub use self::fq::{Fq, FqRepr};
pub use self::fq2::Fq2; pub use self::fq2::Fq2;
pub use self::fq6::Fq6; pub use self::fq6::Fq6;
pub use self::fq12::Fq12; pub use self::fq12::Fq12;
pub use self::ec::{G1, G2, G1Affine, G2Affine, G1Prepared, G2Prepared, G1Uncompressed, G2Uncompressed, G1Compressed, G2Compressed}; pub use self::ec::{G1, G1Affine, G1Compressed, G1Prepared, G1Uncompressed, G2, G2Affine,
G2Compressed, G2Prepared, G2Uncompressed};
use super::{Engine, CurveAffine, Field, BitIterator}; use super::{BitIterator, CurveAffine, Engine, Field};
// The BLS parameter x for BLS12-381 is -0xd201000000010000 // The BLS parameter x for BLS12-381 is -0xd201000000010000
const BLS_X: u64 = 0xd201000000010000; const BLS_X: u64 = 0xd201000000010000;
@@ -35,10 +36,13 @@ impl Engine for Bls12 {
type Fqk = Fq12; type Fqk = Fq12;
fn miller_loop<'a, I>(i: I) -> Self::Fqk fn miller_loop<'a, I>(i: I) -> Self::Fqk
where I: IntoIterator<Item=&'a ( where
&'a <Self::G1Affine as CurveAffine>::Prepared, I: IntoIterator<
&'a <Self::G2Affine as CurveAffine>::Prepared Item = &'a (
)> &'a <Self::G1Affine as CurveAffine>::Prepared,
&'a <Self::G2Affine as CurveAffine>::Prepared,
),
>,
{ {
let mut pairs = vec![]; let mut pairs = vec![];
for &(p, q) in i { for &(p, q) in i {
@@ -48,12 +52,7 @@ impl Engine for Bls12 {
} }
// Twisting isomorphism from E to E' // Twisting isomorphism from E to E'
fn ell( fn ell(f: &mut Fq12, coeffs: &(Fq2, Fq2, Fq2), p: &G1Affine) {
f: &mut Fq12,
coeffs: &(Fq2, Fq2, Fq2),
p: &G1Affine
)
{
let mut c0 = coeffs.0; let mut c0 = coeffs.0;
let mut c1 = coeffs.1; let mut c1 = coeffs.1;
@@ -112,8 +111,7 @@ impl Engine for Bls12 {
r.frobenius_map(2); r.frobenius_map(2);
r.mul_assign(&f2); r.mul_assign(&f2);
fn exp_by_x(f: &mut Fq12, x: u64) fn exp_by_x(f: &mut Fq12, x: u64) {
{
*f = f.pow(&[x]); *f = f.pow(&[x]);
if BLS_X_IS_NEGATIVE { if BLS_X_IS_NEGATIVE {
f.conjugate(); f.conjugate();
@@ -154,8 +152,8 @@ impl Engine for Bls12 {
y1.mul_assign(&y2); y1.mul_assign(&y2);
Some(y1) Some(y1)
}, }
None => None None => None,
} }
} }
} }
@@ -169,14 +167,11 @@ impl G2Prepared {
if q.is_zero() { if q.is_zero() {
return G2Prepared { return G2Prepared {
coeffs: vec![], coeffs: vec![],
infinity: true infinity: true,
} };
} }
fn doubling_step( fn doubling_step(r: &mut G2) -> (Fq2, Fq2, Fq2) {
r: &mut G2
) -> (Fq2, Fq2, Fq2)
{
// Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf // Adaptation of Algorithm 26, https://eprint.iacr.org/2010/354.pdf
let mut tmp0 = r.x; let mut tmp0 = r.x;
tmp0.square(); tmp0.square();
@@ -247,11 +242,7 @@ impl G2Prepared {
(tmp0, tmp3, tmp6) (tmp0, tmp3, tmp6)
} }
fn addition_step( fn addition_step(r: &mut G2, q: &G2Affine) -> (Fq2, Fq2, Fq2) {
r: &mut G2,
q: &G2Affine
) -> (Fq2, Fq2, Fq2)
{
// Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf // Adaptation of Algorithm 27, https://eprint.iacr.org/2010/354.pdf
let mut zsquared = r.z; let mut zsquared = r.z;
zsquared.square(); zsquared.square();
@@ -360,7 +351,7 @@ impl G2Prepared {
G2Prepared { G2Prepared {
coeffs: coeffs, coeffs: coeffs,
infinity: false infinity: false,
} }
} }
} }

View File

@@ -52,8 +52,7 @@ fn test_pairing_result_against_relic() {
}); });
} }
fn test_vectors<G: CurveProjective, E: EncodedPoint<Affine=G::Affine>>(expected: &[u8]) fn test_vectors<G: CurveProjective, E: EncodedPoint<Affine = G::Affine>>(expected: &[u8]) {
{
let mut e = G::zero(); let mut e = G::zero();
let mut v = vec![]; let mut v = vec![];
@@ -198,9 +197,11 @@ fn test_g1_uncompressed_invalid_vectors() {
y.into_repr().write_be(&mut o.as_mut()[48..]).unwrap(); y.into_repr().write_be(&mut o.as_mut()[48..]).unwrap();
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() { if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break break;
} else { } else {
panic!("should have rejected the point because it isn't in the correct subgroup") panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
} }
} else { } else {
x.add_assign(&Fq::one()); x.add_assign(&Fq::one());
@@ -327,7 +328,7 @@ fn test_g2_uncompressed_invalid_vectors() {
x3b.mul_assign(&x); x3b.mul_assign(&x);
x3b.add_assign(&Fq2 { x3b.add_assign(&Fq2 {
c0: Fq::from_repr(FqRepr::from(4)).unwrap(), c0: Fq::from_repr(FqRepr::from(4)).unwrap(),
c1: Fq::from_repr(FqRepr::from(4)).unwrap() c1: Fq::from_repr(FqRepr::from(4)).unwrap(),
}); // TODO: perhaps expose coeff_b through API? }); // TODO: perhaps expose coeff_b through API?
if let Some(y) = x3b.sqrt() { if let Some(y) = x3b.sqrt() {
@@ -338,9 +339,11 @@ fn test_g2_uncompressed_invalid_vectors() {
y.c0.into_repr().write_be(&mut o.as_mut()[144..]).unwrap(); y.c0.into_repr().write_be(&mut o.as_mut()[144..]).unwrap();
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() { if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break break;
} else { } else {
panic!("should have rejected the point because it isn't in the correct subgroup") panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
} }
} else { } else {
x.add_assign(&Fq2::one()); x.add_assign(&Fq2::one());
@@ -428,7 +431,7 @@ fn test_g1_compressed_invalid_vectors() {
o.as_mut()[0] |= 0b1000_0000; o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() { if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
break break;
} else { } else {
panic!("should have rejected the point because it isn't on the curve") panic!("should have rejected the point because it isn't on the curve")
} }
@@ -452,9 +455,11 @@ fn test_g1_compressed_invalid_vectors() {
o.as_mut()[0] |= 0b1000_0000; o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() { if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break break;
} else { } else {
panic!("should have rejected the point because it isn't in the correct subgroup") panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
} }
} else { } else {
x.add_assign(&Fq::one()); x.add_assign(&Fq::one());
@@ -541,7 +546,7 @@ fn test_g2_compressed_invalid_vectors() {
let mut o = o; let mut o = o;
let mut x = Fq2 { let mut x = Fq2 {
c0: Fq::one(), c0: Fq::one(),
c1: Fq::one() c1: Fq::one(),
}; };
loop { loop {
@@ -561,7 +566,7 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[0] |= 0b1000_0000; o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() { if let Err(GroupDecodingError::NotOnCurve) = o.into_affine() {
break break;
} else { } else {
panic!("should have rejected the point because it isn't on the curve") panic!("should have rejected the point because it isn't on the curve")
} }
@@ -573,7 +578,7 @@ fn test_g2_compressed_invalid_vectors() {
let mut o = o; let mut o = o;
let mut x = Fq2 { let mut x = Fq2 {
c0: Fq::one(), c0: Fq::one(),
c1: Fq::one() c1: Fq::one(),
}; };
loop { loop {
@@ -592,9 +597,11 @@ fn test_g2_compressed_invalid_vectors() {
o.as_mut()[0] |= 0b1000_0000; o.as_mut()[0] |= 0b1000_0000;
if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() { if let Err(GroupDecodingError::NotInSubgroup) = o.into_affine() {
break break;
} else { } else {
panic!("should have rejected the point because it isn't in the correct subgroup") panic!(
"should have rejected the point because it isn't in the correct subgroup"
)
} }
} else { } else {
x.add_assign(&Fq2::one()); x.add_assign(&Fq2::one());

View File

@@ -1,7 +1,6 @@
// If the "u128-support" feature is enabled, this library can use // If the "u128-support" feature is enabled, this library can use
// more efficient arithmetic. Only available in the nightly compiler. // more efficient arithmetic. Only available in the nightly compiler.
#![cfg_attr(feature = "u128-support", feature(i128_type))] #![cfg_attr(feature = "u128-support", feature(i128_type))]
// `clippy` is a code linting tool for improving code quality by catching // `clippy` is a code linting tool for improving code quality by catching
// common mistakes or strange code patterns. If the `clippy` feature is // common mistakes or strange code patterns. If the `clippy` feature is
// provided, it is enabled and all compiler warnings are prohibited. // provided, it is enabled and all compiler warnings are prohibited.
@@ -13,12 +12,11 @@
#![cfg_attr(feature = "clippy", allow(unreadable_literal))] #![cfg_attr(feature = "clippy", allow(unreadable_literal))]
#![cfg_attr(feature = "clippy", allow(many_single_char_names))] #![cfg_attr(feature = "clippy", allow(many_single_char_names))]
#![cfg_attr(feature = "clippy", allow(new_without_default_derive))] #![cfg_attr(feature = "clippy", allow(new_without_default_derive))]
// Force public structures to implement Debug // Force public structures to implement Debug
#![deny(missing_debug_implementations)] #![deny(missing_debug_implementations)]
extern crate rand;
extern crate byteorder; extern crate byteorder;
extern crate rand;
#[cfg(test)] #[cfg(test)]
pub mod tests; pub mod tests;
@@ -35,22 +33,49 @@ use std::io::{self, Read, Write};
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.) /// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
/// with well-defined relationships. In particular, the G1/G2 curve groups are /// with well-defined relationships. In particular, the G1/G2 curve groups are
/// of prime order `r`, and are equipped with a bilinear pairing function. /// of prime order `r`, and are equipped with a bilinear pairing function.
pub trait Engine: Sized + 'static + Clone pub trait Engine: Sized + 'static + Clone {
{
/// This is the scalar field of the G1/G2 groups. /// This is the scalar field of the G1/G2 groups.
type Fr: PrimeField + SqrtField; type Fr: PrimeField + SqrtField;
/// The projective representation of an element in G1. /// The projective representation of an element in G1.
type G1: CurveProjective<Engine=Self, Base=Self::Fq, Scalar=Self::Fr, Affine=Self::G1Affine> + From<Self::G1Affine>; type G1: CurveProjective<
Engine = Self,
Base = Self::Fq,
Scalar = Self::Fr,
Affine = Self::G1Affine,
>
+ From<Self::G1Affine>;
/// The affine representation of an element in G1. /// The affine representation of an element in G1.
type G1Affine: CurveAffine<Engine=Self, Base=Self::Fq, Scalar=Self::Fr, Projective=Self::G1, Pair=Self::G2Affine, PairingResult=Self::Fqk> + From<Self::G1>; type G1Affine: CurveAffine<
Engine = Self,
Base = Self::Fq,
Scalar = Self::Fr,
Projective = Self::G1,
Pair = Self::G2Affine,
PairingResult = Self::Fqk,
>
+ From<Self::G1>;
/// The projective representation of an element in G2. /// The projective representation of an element in G2.
type G2: CurveProjective<Engine=Self, Base=Self::Fqe, Scalar=Self::Fr, Affine=Self::G2Affine> + From<Self::G2Affine>; type G2: CurveProjective<
Engine = Self,
Base = Self::Fqe,
Scalar = Self::Fr,
Affine = Self::G2Affine,
>
+ From<Self::G2Affine>;
/// The affine representation of an element in G2. /// The affine representation of an element in G2.
type G2Affine: CurveAffine<Engine=Self, Base=Self::Fqe, Scalar=Self::Fr, Projective=Self::G2, Pair=Self::G1Affine, PairingResult=Self::Fqk> + From<Self::G2>; type G2Affine: CurveAffine<
Engine = Self,
Base = Self::Fqe,
Scalar = Self::Fr,
Projective = Self::G2,
Pair = Self::G1Affine,
PairingResult = Self::Fqk,
>
+ From<Self::G2>;
/// The base field that hosts G1. /// The base field that hosts G1.
type Fq: PrimeField + SqrtField; type Fq: PrimeField + SqrtField;
@@ -63,46 +88,47 @@ pub trait Engine: Sized + 'static + Clone
/// Perform a miller loop with some number of (G1, G2) pairs. /// Perform a miller loop with some number of (G1, G2) pairs.
fn miller_loop<'a, I>(i: I) -> Self::Fqk fn miller_loop<'a, I>(i: I) -> Self::Fqk
where I: IntoIterator<Item=&'a ( where
&'a <Self::G1Affine as CurveAffine>::Prepared, I: IntoIterator<
&'a <Self::G2Affine as CurveAffine>::Prepared Item = &'a (
)>; &'a <Self::G1Affine as CurveAffine>::Prepared,
&'a <Self::G2Affine as CurveAffine>::Prepared,
),
>;
/// Perform final exponentiation of the result of a miller loop. /// Perform final exponentiation of the result of a miller loop.
fn final_exponentiation(&Self::Fqk) -> Option<Self::Fqk>; fn final_exponentiation(&Self::Fqk) -> Option<Self::Fqk>;
/// Performs a complete pairing operation `(p, q)`. /// Performs a complete pairing operation `(p, q)`.
fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk
where G1: Into<Self::G1Affine>, where
G2: Into<Self::G2Affine> G1: Into<Self::G1Affine>,
G2: Into<Self::G2Affine>,
{ {
Self::final_exponentiation(&Self::miller_loop( Self::final_exponentiation(&Self::miller_loop(
[( [(&(p.into().prepare()), &(q.into().prepare()))].into_iter(),
&(p.into().prepare()),
&(q.into().prepare())
)].into_iter()
)).unwrap() )).unwrap()
} }
} }
/// Projective representation of an elliptic curve point guaranteed to be /// Projective representation of an elliptic curve point guaranteed to be
/// in the correct prime order subgroup. /// in the correct prime order subgroup.
pub trait CurveProjective: PartialEq + pub trait CurveProjective
Eq + : PartialEq
Sized + + Eq
Copy + + Sized
Clone + + Copy
Send + + Clone
Sync + + Send
fmt::Debug + + Sync
fmt::Display + + fmt::Debug
rand::Rand + + fmt::Display
'static + rand::Rand
{ + 'static {
type Engine: Engine<Fr=Self::Scalar>; type Engine: Engine<Fr = Self::Scalar>;
type Scalar: PrimeField + SqrtField; type Scalar: PrimeField + SqrtField;
type Base: SqrtField; type Base: SqrtField;
type Affine: CurveAffine<Projective=Self, Scalar=Self::Scalar>; type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>;
/// Returns the additive identity. /// Returns the additive identity.
fn zero() -> Self; fn zero() -> Self;
@@ -157,25 +183,17 @@ pub trait CurveProjective: PartialEq +
/// Affine representation of an elliptic curve point guaranteed to be /// Affine representation of an elliptic curve point guaranteed to be
/// in the correct prime order subgroup. /// in the correct prime order subgroup.
pub trait CurveAffine: Copy + pub trait CurveAffine
Clone + : Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static
Sized + {
Send + type Engine: Engine<Fr = Self::Scalar>;
Sync +
fmt::Debug +
fmt::Display +
PartialEq +
Eq +
'static
{
type Engine: Engine<Fr=Self::Scalar>;
type Scalar: PrimeField + SqrtField; type Scalar: PrimeField + SqrtField;
type Base: SqrtField; type Base: SqrtField;
type Projective: CurveProjective<Affine=Self, Scalar=Self::Scalar>; type Projective: CurveProjective<Affine = Self, Scalar = Self::Scalar>;
type Prepared: Clone + Send + Sync + 'static; type Prepared: Clone + Send + Sync + 'static;
type Uncompressed: EncodedPoint<Affine=Self>; type Uncompressed: EncodedPoint<Affine = Self>;
type Compressed: EncodedPoint<Affine=Self>; type Compressed: EncodedPoint<Affine = Self>;
type Pair: CurveAffine<Pair=Self>; type Pair: CurveAffine<Pair = Self>;
type PairingResult: Field; type PairingResult: Field;
/// Returns the additive identity. /// Returns the additive identity.
@@ -217,15 +235,8 @@ pub trait CurveAffine: Copy +
} }
/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`. /// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`.
pub trait EncodedPoint: Sized + pub trait EncodedPoint
Send + : Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static {
Sync +
AsRef<[u8]> +
AsMut<[u8]> +
Clone +
Copy +
'static
{
type Affine: CurveAffine; type Affine: CurveAffine;
/// Creates an empty representation. /// Creates an empty representation.
@@ -253,17 +264,9 @@ pub trait EncodedPoint: Sized +
} }
/// This trait represents an element of a field. /// This trait represents an element of a field.
pub trait Field: Sized + pub trait Field
Eq + : Sized + Eq + Copy + Clone + Send + Sync + fmt::Debug + fmt::Display + 'static + rand::Rand
Copy + {
Clone +
Send +
Sync +
fmt::Debug +
fmt::Display +
'static +
rand::Rand
{
/// Returns the zero element of the field, the additive identity. /// Returns the zero element of the field, the additive identity.
fn zero() -> Self; fn zero() -> Self;
@@ -300,8 +303,7 @@ pub trait Field: Sized +
/// Exponentiates this element by a number represented with `u64` limbs, /// Exponentiates this element by a number represented with `u64` limbs,
/// least significant digit first. /// least significant digit first.
fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self fn pow<S: AsRef<[u64]>>(&self, exp: S) -> Self {
{
let mut res = Self::one(); let mut res = Self::one();
let mut found_one = false; let mut found_one = false;
@@ -323,8 +325,7 @@ pub trait Field: Sized +
} }
/// This trait represents an element of a field that has a square root operation described for it. /// This trait represents an element of a field that has a square root operation described for it.
pub trait SqrtField: Field pub trait SqrtField: Field {
{
/// Returns the Legendre symbol of the field element. /// Returns the Legendre symbol of the field element.
fn legendre(&self) -> LegendreSymbol; fn legendre(&self) -> LegendreSymbol;
@@ -333,26 +334,25 @@ pub trait SqrtField: Field
fn sqrt(&self) -> Option<Self>; fn sqrt(&self) -> Option<Self>;
} }
/// This trait represents a wrapper around a biginteger which can encode any element of a particular /// This trait represents a wrapper around a biginteger which can encode any element of a particular
/// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit /// prime field. It is a smart wrapper around a sequence of `u64` limbs, least-significant digit
/// first. /// first.
pub trait PrimeFieldRepr: Sized + pub trait PrimeFieldRepr
Copy + : Sized
Clone + + Copy
Eq + + Clone
Ord + + Eq
Send + + Ord
Sync + + Send
Default + + Sync
fmt::Debug + + Default
fmt::Display + + fmt::Debug
'static + + fmt::Display
rand::Rand + + 'static
AsRef<[u64]> + + rand::Rand
AsMut<[u64]> + + AsRef<[u64]>
From<u64> + AsMut<[u64]>
{ + From<u64> {
/// Subtract another represetation from this one. /// Subtract another represetation from this one.
fn sub_noborrow(&mut self, other: &Self); fn sub_noborrow(&mut self, other: &Self);
@@ -388,7 +388,7 @@ pub trait PrimeFieldRepr: Sized +
/// Writes this `PrimeFieldRepr` as a big endian integer. /// Writes this `PrimeFieldRepr` as a big endian integer.
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> { fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
use byteorder::{WriteBytesExt, BigEndian}; use byteorder::{BigEndian, WriteBytesExt};
for digit in self.as_ref().iter().rev() { for digit in self.as_ref().iter().rev() {
writer.write_u64::<BigEndian>(*digit)?; writer.write_u64::<BigEndian>(*digit)?;
@@ -399,7 +399,7 @@ pub trait PrimeFieldRepr: Sized +
/// Reads a big endian integer into this representation. /// Reads a big endian integer into this representation.
fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> { fn read_be<R: Read>(&mut self, mut reader: R) -> io::Result<()> {
use byteorder::{ReadBytesExt, BigEndian}; use byteorder::{BigEndian, ReadBytesExt};
for digit in self.as_mut().iter_mut().rev() { for digit in self.as_mut().iter_mut().rev() {
*digit = reader.read_u64::<BigEndian>()?; *digit = reader.read_u64::<BigEndian>()?;
@@ -413,7 +413,7 @@ pub trait PrimeFieldRepr: Sized +
pub enum LegendreSymbol { pub enum LegendreSymbol {
Zero = 0, Zero = 0,
QuadraticResidue = 1, QuadraticResidue = 1,
QuadraticNonResidue = -1 QuadraticNonResidue = -1,
} }
/// An error that may occur when trying to interpret a `PrimeFieldRepr` as a /// An error that may occur when trying to interpret a `PrimeFieldRepr` as a
@@ -421,13 +421,13 @@ pub enum LegendreSymbol {
#[derive(Debug)] #[derive(Debug)]
pub enum PrimeFieldDecodingError { pub enum PrimeFieldDecodingError {
/// The encoded value is not in the field /// The encoded value is not in the field
NotInField(String) NotInField(String),
} }
impl Error for PrimeFieldDecodingError { impl Error for PrimeFieldDecodingError {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
PrimeFieldDecodingError::NotInField(..) => "not an element of the field" PrimeFieldDecodingError::NotInField(..) => "not an element of the field",
} }
} }
} }
@@ -454,7 +454,7 @@ pub enum GroupDecodingError {
/// The compression mode of the encoded element was not as expected /// The compression mode of the encoded element was not as expected
UnexpectedCompressionMode, UnexpectedCompressionMode,
/// The encoding contained bits that should not have been set /// The encoding contained bits that should not have been set
UnexpectedInformation UnexpectedInformation,
} }
impl Error for GroupDecodingError { impl Error for GroupDecodingError {
@@ -463,8 +463,10 @@ impl Error for GroupDecodingError {
GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve", GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup", GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded", GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
GroupDecodingError::UnexpectedCompressionMode => "encoding has unexpected compression mode", GroupDecodingError::UnexpectedCompressionMode => {
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information" "encoding has unexpected compression mode"
}
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
} }
} }
} }
@@ -474,17 +476,14 @@ impl fmt::Display for GroupDecodingError {
match *self { match *self {
GroupDecodingError::CoordinateDecodingError(description, ref err) => { GroupDecodingError::CoordinateDecodingError(description, ref err) => {
write!(f, "{} decoding error: {}", description, err) write!(f, "{} decoding error: {}", description, err)
},
_ => {
write!(f, "{}", self.description())
} }
_ => write!(f, "{}", self.description()),
} }
} }
} }
/// This represents an element of a prime field. /// This represents an element of a prime field.
pub trait PrimeField: Field pub trait PrimeField: Field {
{
/// The prime field can be converted back and forth into this biginteger /// The prime field can be converted back and forth into this biginteger
/// representation. /// representation.
type Repr: PrimeFieldRepr + From<Self>; type Repr: PrimeFieldRepr + From<Self>;
@@ -519,7 +518,7 @@ pub trait PrimeField: Field
res.mul_assign(&ten); res.mul_assign(&ten);
res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap()); res.add_assign(&Self::from_repr(Self::Repr::from(u64::from(c))).unwrap());
}, }
None => { None => {
return None; return None;
} }
@@ -560,17 +559,14 @@ pub trait PrimeField: Field
#[derive(Debug)] #[derive(Debug)]
pub struct BitIterator<E> { pub struct BitIterator<E> {
t: E, t: E,
n: usize n: usize,
} }
impl<E: AsRef<[u64]>> BitIterator<E> { impl<E: AsRef<[u64]>> BitIterator<E> {
pub fn new(t: E) -> Self { pub fn new(t: E) -> Self {
let n = t.as_ref().len() * 64; let n = t.as_ref().len() * 64;
BitIterator { BitIterator { t: t, n: n }
t: t,
n: n
}
} }
} }
@@ -603,7 +599,12 @@ fn test_bit_iterator() {
let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001"; let expected = "1010010101111110101010000101101011101000011101110101001000011001100100100011011010001011011011010001011011101100110100111011010010110001000011110100110001100110011101101000101100011100100100100100001010011101010111110011101011000011101000111011011101011001";
let mut a = BitIterator::new([0x429d5f3ac3a3b759, 0xb10f4c66768b1c92, 0x92368b6d16ecd3b4, 0xa57ea85ae8775219]); let mut a = BitIterator::new([
0x429d5f3ac3a3b759,
0xb10f4c66768b1c92,
0x92368b6d16ecd3b4,
0xa57ea85ae8775219,
]);
for e in expected.chars() { for e in expected.chars() {
assert!(a.next().unwrap() == (e == '1')); assert!(a.next().unwrap() == (e == '1'));

View File

@@ -1,9 +1,8 @@
use rand::{SeedableRng, XorShiftRng, Rand, Rng}; use rand::{Rand, Rng, SeedableRng, XorShiftRng};
use ::{CurveProjective, CurveAffine, Field, EncodedPoint}; use {CurveAffine, CurveProjective, EncodedPoint, Field};
pub fn curve_tests<G: CurveProjective>() pub fn curve_tests<G: CurveProjective>() {
{
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
// Negation edge case with zero. // Negation edge case with zero.
@@ -48,7 +47,10 @@ pub fn curve_tests<G: CurveProjective>()
{ {
let a = G::rand(&mut rng); let a = G::rand(&mut rng);
let b = a.into_affine().into_projective(); let b = a.into_affine().into_projective();
let c = a.into_affine().into_projective().into_affine().into_projective(); let c = a.into_affine()
.into_projective()
.into_affine()
.into_projective();
assert_eq!(a, b); assert_eq!(a, b);
assert_eq!(b, c); assert_eq!(b, c);
} }
@@ -63,8 +65,8 @@ pub fn curve_tests<G: CurveProjective>()
} }
fn random_wnaf_tests<G: CurveProjective>() { fn random_wnaf_tests<G: CurveProjective>() {
use ::wnaf::*; use wnaf::*;
use ::PrimeField; use PrimeField;
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@@ -89,7 +91,7 @@ fn random_wnaf_tests<G: CurveProjective>() {
} }
{ {
fn only_compiles_if_send<S: Send>(_: &S) { } fn only_compiles_if_send<S: Send>(_: &S) {}
for _ in 0..100 { for _ in 0..100 {
let g = G::rand(&mut rng); let g = G::rand(&mut rng);
@@ -370,7 +372,9 @@ fn random_transformation_tests<G: CurveProjective>() {
v[s] = v[s].into_affine().into_projective(); v[s] = v[s].into_affine().into_projective();
} }
let expected_v = v.iter().map(|v| v.into_affine().into_projective()).collect::<Vec<_>>(); let expected_v = v.iter()
.map(|v| v.into_affine().into_projective())
.collect::<Vec<_>>();
G::batch_normalization(&mut v); G::batch_normalization(&mut v);
for i in &v { for i in &v {
@@ -381,8 +385,7 @@ fn random_transformation_tests<G: CurveProjective>() {
} }
} }
fn random_encoding_tests<G: CurveAffine>() fn random_encoding_tests<G: CurveAffine>() {
{
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
assert_eq!( assert_eq!(

View File

@@ -1,9 +1,8 @@
use rand::{SeedableRng, XorShiftRng, Rand}; use rand::{Rand, SeedableRng, XorShiftRng};
use ::{Engine, CurveProjective, CurveAffine, Field, PrimeField}; use {CurveAffine, CurveProjective, Engine, Field, PrimeField};
pub fn engine_tests<E: Engine>() pub fn engine_tests<E: Engine>() {
{
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..10 { for _ in 0..10 {
@@ -84,9 +83,8 @@ fn random_miller_loop_tests<E: Engine>() {
let c = c.into_affine().prepare(); let c = c.into_affine().prepare();
let d = d.into_affine().prepare(); let d = d.into_affine().prepare();
let abcd_with_double_loop = E::final_exponentiation( let abcd_with_double_loop =
&E::miller_loop(&[(&a, &b), (&c, &d)]) E::final_exponentiation(&E::miller_loop(&[(&a, &b), (&c, &d)])).unwrap();
).unwrap();
assert_eq!(abcd, abcd_with_double_loop); assert_eq!(abcd, abcd_with_double_loop);
} }

View File

@@ -1,11 +1,11 @@
use rand::{Rng, SeedableRng, XorShiftRng}; use rand::{Rng, SeedableRng, XorShiftRng};
use ::{SqrtField, Field, PrimeField, LegendreSymbol}; use {Field, LegendreSymbol, PrimeField, SqrtField};
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) { pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]); let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..100 { for _ in 0..100 {
for i in 0..(maxpower+1) { for i in 0..(maxpower + 1) {
let mut a = F::rand(&mut rng); let mut a = F::rand(&mut rng);
let mut b = a; let mut b = a;

View File

@@ -1,5 +1,5 @@
use rand::{SeedableRng, XorShiftRng}; use rand::{SeedableRng, XorShiftRng};
use ::{PrimeFieldRepr}; use PrimeFieldRepr;
pub fn random_repr_tests<R: PrimeFieldRepr>() { pub fn random_repr_tests<R: PrimeFieldRepr>() {
random_encoding_tests::<R>(); random_encoding_tests::<R>();
@@ -28,7 +28,7 @@ fn random_shl_tests<R: PrimeFieldRepr>() {
for _ in 0..100 { for _ in 0..100 {
let r = R::rand(&mut rng); let r = R::rand(&mut rng);
for shift in 0..(r.num_bits()+1) { for shift in 0..(r.num_bits() + 1) {
let mut r1 = r; let mut r1 = r;
let mut r2 = r; let mut r2 = r;
@@ -49,7 +49,7 @@ fn random_shr_tests<R: PrimeFieldRepr>() {
for _ in 0..100 { for _ in 0..100 {
let r = R::rand(&mut rng); let r = R::rand(&mut rng);
for shift in 0..(r.num_bits()+1) { for shift in 0..(r.num_bits() + 1) {
let mut r1 = r; let mut r1 = r;
let mut r2 = r; let mut r2 = r;

View File

@@ -1,32 +1,30 @@
use super::{CurveProjective, PrimeFieldRepr, PrimeField}; use super::{CurveProjective, PrimeField, PrimeFieldRepr};
/// Replaces the contents of `table` with a w-NAF window table for the given window size. /// Replaces the contents of `table` with a w-NAF window table for the given window size.
pub(crate) fn wnaf_table<G: CurveProjective>(table: &mut Vec<G>, mut base: G, window: usize) pub(crate) fn wnaf_table<G: CurveProjective>(table: &mut Vec<G>, mut base: G, window: usize) {
{
table.truncate(0); table.truncate(0);
table.reserve(1 << (window-1)); table.reserve(1 << (window - 1));
let mut dbl = base; let mut dbl = base;
dbl.double(); dbl.double();
for _ in 0..(1 << (window-1)) { for _ in 0..(1 << (window - 1)) {
table.push(base); table.push(base);
base.add_assign(&dbl); base.add_assign(&dbl);
} }
} }
/// Replaces the contents of `wnaf` with the w-NAF representation of a scalar. /// Replaces the contents of `wnaf` with the w-NAF representation of a scalar.
pub(crate) fn wnaf_form<S: PrimeFieldRepr>(wnaf: &mut Vec<i64>, mut c: S, window: usize) pub(crate) fn wnaf_form<S: PrimeFieldRepr>(wnaf: &mut Vec<i64>, mut c: S, window: usize) {
{
wnaf.truncate(0); wnaf.truncate(0);
while !c.is_zero() { while !c.is_zero() {
let mut u; let mut u;
if c.is_odd() { if c.is_odd() {
u = (c.as_ref()[0] % (1 << (window+1))) as i64; u = (c.as_ref()[0] % (1 << (window + 1))) as i64;
if u > (1 << window) { if u > (1 << window) {
u -= 1 << (window+1); u -= 1 << (window + 1);
} }
if u > 0 { if u > 0 {
@@ -48,8 +46,7 @@ pub(crate) fn wnaf_form<S: PrimeFieldRepr>(wnaf: &mut Vec<i64>, mut c: S, window
/// ///
/// This function must be provided a `table` and `wnaf` that were constructed with /// This function must be provided a `table` and `wnaf` that were constructed with
/// the same window size; otherwise, it may panic or produce invalid results. /// the same window size; otherwise, it may panic or produce invalid results.
pub(crate) fn wnaf_exp<G: CurveProjective>(table: &[G], wnaf: &[i64]) -> G pub(crate) fn wnaf_exp<G: CurveProjective>(table: &[G], wnaf: &[i64]) -> G {
{
let mut result = G::zero(); let mut result = G::zero();
let mut found_one = false; let mut found_one = false;
@@ -63,9 +60,9 @@ pub(crate) fn wnaf_exp<G: CurveProjective>(table: &[G], wnaf: &[i64]) -> G
found_one = true; found_one = true;
if *n > 0 { if *n > 0 {
result.add_assign(&table[(n/2) as usize]); result.add_assign(&table[(n / 2) as usize]);
} else { } else {
result.sub_assign(&table[((-n)/2) as usize]); result.sub_assign(&table[((-n) / 2) as usize]);
} }
} }
} }
@@ -78,7 +75,7 @@ pub(crate) fn wnaf_exp<G: CurveProjective>(table: &[G], wnaf: &[i64]) -> G
pub struct Wnaf<W, B, S> { pub struct Wnaf<W, B, S> {
base: B, base: B,
scalar: S, scalar: S,
window_size: W window_size: W,
} }
impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> { impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
@@ -87,18 +84,13 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
Wnaf { Wnaf {
base: vec![], base: vec![],
scalar: vec![], scalar: vec![],
window_size: () window_size: (),
} }
} }
/// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that /// Given a base and a number of scalars, compute a window table and return a `Wnaf` object that
/// can perform exponentiations with `.scalar(..)`. /// can perform exponentiations with `.scalar(..)`.
pub fn base( pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf<usize, &[G], &mut Vec<i64>> {
&mut self,
base: G,
num_scalars: usize
) -> Wnaf<usize, &[G], &mut Vec<i64>>
{
// Compute the appropriate window size based on the number of scalars. // Compute the appropriate window size based on the number of scalars.
let window_size = G::recommended_wnaf_for_num_scalars(num_scalars); let window_size = G::recommended_wnaf_for_num_scalars(num_scalars);
@@ -110,7 +102,7 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
Wnaf { Wnaf {
base: &self.base[..], base: &self.base[..],
scalar: &mut self.scalar, scalar: &mut self.scalar,
window_size: window_size window_size: window_size,
} }
} }
@@ -118,9 +110,8 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
/// exponentiations with `.base(..)`. /// exponentiations with `.base(..)`.
pub fn scalar( pub fn scalar(
&mut self, &mut self,
scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
) -> Wnaf<usize, &mut Vec<G>, &[i64]> ) -> Wnaf<usize, &mut Vec<G>, &[i64]> {
{
// Compute the appropriate window size for the scalar. // Compute the appropriate window size for the scalar.
let window_size = G::recommended_wnaf_for_scalar(scalar); let window_size = G::recommended_wnaf_for_scalar(scalar);
@@ -132,7 +123,7 @@ impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
Wnaf { Wnaf {
base: &mut self.base, base: &mut self.base,
scalar: &self.scalar[..], scalar: &self.scalar[..],
window_size: window_size window_size: window_size,
} }
} }
} }
@@ -144,7 +135,7 @@ impl<'a, G: CurveProjective> Wnaf<usize, &'a [G], &'a mut Vec<i64>> {
Wnaf { Wnaf {
base: self.base, base: self.base,
scalar: vec![], scalar: vec![],
window_size: self.window_size window_size: self.window_size,
} }
} }
} }
@@ -157,18 +148,16 @@ impl<'a, G: CurveProjective> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
Wnaf { Wnaf {
base: vec![], base: vec![],
scalar: self.scalar, scalar: self.scalar,
window_size: self.window_size window_size: self.window_size,
} }
} }
} }
impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> { impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
/// Performs exponentiation given a base. /// Performs exponentiation given a base.
pub fn base<G: CurveProjective>( pub fn base<G: CurveProjective>(&mut self, base: G) -> G
&mut self, where
base: G B: AsMut<Vec<G>>,
) -> G
where B: AsMut<Vec<G>>
{ {
wnaf_table(self.base.as_mut(), base, self.window_size); wnaf_table(self.base.as_mut(), base, self.window_size);
wnaf_exp(self.base.as_mut(), self.scalar.as_ref()) wnaf_exp(self.base.as_mut(), self.scalar.as_ref())
@@ -179,9 +168,10 @@ impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> {
/// Performs exponentiation given a scalar. /// Performs exponentiation given a scalar.
pub fn scalar<G: CurveProjective>( pub fn scalar<G: CurveProjective>(
&mut self, &mut self,
scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
) -> G ) -> G
where B: AsRef<[G]> where
B: AsRef<[G]>,
{ {
wnaf_form(self.scalar.as_mut(), scalar, self.window_size); wnaf_form(self.scalar.as_mut(), scalar, self.window_size);
wnaf_exp(self.base.as_ref(), self.scalar.as_mut()) wnaf_exp(self.base.as_ref(), self.scalar.as_mut())