Apply rustfmt to the codebase.

This commit is contained in:
Sean Bowe 2018-02-21 11:08:58 -07:00
parent d51a5b0122
commit 53083f4290
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
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,8 +367,8 @@ 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,11 +1,10 @@
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 {
let a = E::G1::rand(&mut rng).into_affine(); let a = E::G1::rand(&mut rng).into_affine();
let b = E::G2::rand(&mut rng).into_affine(); let b = E::G2::rand(&mut rng).into_affine();
@ -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())