Auto merge of #26 - ebfull:even-more-adjustments, r=ebfull

Even more adjustments

Closes #22
Closes #24
Closes #25
This commit is contained in:
bmerge 2017-08-01 17:38:38 +00:00
commit d72929f64e
8 changed files with 213 additions and 31 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "pairing"
version = "0.10.1"
version = "0.10.2"
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
license = "MIT/Apache-2.0"
@ -12,7 +12,7 @@ repository = "https://github.com/ebfull/pairing"
[dependencies]
rand = "0.3"
byteorder = "1.1.0"
clippy = { version = "0.0.145", optional = true }
clippy = { version = "0.0.148", optional = true }
[features]
unstable-wnaf = []

View File

@ -108,6 +108,7 @@ macro_rules! curve_impl {
}
impl CurveAffine for $affine {
type Engine = Bls12;
type Scalar = $scalarfield;
type Base = $basefield;
type Prepared = $prepared;
@ -174,6 +175,7 @@ macro_rules! curve_impl {
}
impl CurveProjective for $projective {
type Engine = Bls12;
type Scalar = $scalarfield;
type Base = $basefield;
type Affine = $affine;
@ -582,7 +584,7 @@ macro_rules! curve_impl {
pub mod g1 {
use rand::{Rand, Rng};
use super::g2::G2Affine;
use super::super::{Fq, Fr, FrRepr, FqRepr, Fq12};
use super::super::{Bls12, Fq, Fr, FrRepr, FqRepr, Fq12};
use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};
curve_impl!("G1", G1, G1Affine, G1Prepared, Fq, Fr, G1Uncompressed, G1Compressed, G2Affine);
@ -1134,7 +1136,7 @@ pub mod g1 {
pub mod g2 {
use rand::{Rand, Rng};
use super::super::{Fq2, Fr, Fq, FrRepr, FqRepr, Fq12};
use super::super::{Bls12, Fq2, Fr, Fq, FrRepr, FqRepr, Fq12};
use super::g1::G1Affine;
use ::{CurveProjective, CurveAffine, PrimeField, SqrtField, PrimeFieldRepr, Field, BitIterator, EncodedPoint, GroupDecodingError, Engine};

View File

@ -10,7 +10,7 @@ const MODULUS_BITS: u32 = 381;
// The number of bits that must be shaved from the beginning of
// the representation when randomly sampling.
const REPR_SHAVE_BITS: usize = 3;
const REPR_SHAVE_BITS: u32 = 3;
// R = 2**384 % q
const R: FqRepr = FqRepr([0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493]);
@ -25,7 +25,7 @@ const INV: u64 = 0x89f3fffcfffcfffd;
const GENERATOR: FqRepr = FqRepr([0x321300000006554f, 0xb93c0018d6c40005, 0x57605e0db0ddbb51, 0x8b256521ed1f9bcb, 0x6cf28d7901622c03, 0x11ebab9dbb81e28c]);
// 2^s * t = MODULUS - 1 with t odd
const S: usize = 1;
const S: u32 = 1;
// 2^s root of unity computed by GENERATOR^t
const ROOT_OF_UNITY: FqRepr = FqRepr([0x43f5fffffffcaaae, 0x32b7fff2ed47fffd, 0x7e83a49a2e99d69, 0xeca8f3318332bb7a, 0xef148d1ea0f4c069, 0x40ab3263eff0206]);
@ -278,7 +278,7 @@ impl PrimeFieldRepr for FqRepr {
}
#[inline(always)]
fn divn(&mut self, mut n: usize) {
fn divn(&mut self, mut n: u32) {
if n >= 64 * 6 {
*self = Self::from(0);
return;
@ -325,6 +325,32 @@ impl PrimeFieldRepr for FqRepr {
}
}
#[inline(always)]
fn muln(&mut self, mut n: u32) {
if n >= 64 * 6 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in &mut self.0 {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (6 as u32) * 64;
@ -444,7 +470,7 @@ impl PrimeField for Fq {
Fq(GENERATOR)
}
fn s() -> usize {
fn s() -> u32 {
S
}
@ -1740,6 +1766,7 @@ fn fq_field_tests() {
::tests::field::random_field_tests::<Fq>();
::tests::field::random_sqrt_tests::<Fq>();
::tests::field::random_frobenius_tests::<Fq, _>(Fq::char(), 13);
::tests::field::from_str_tests::<Fq>();
}
#[test]

View File

@ -8,7 +8,7 @@ const MODULUS_BITS: u32 = 255;
// The number of bits that must be shaved from the beginning of
// the representation when randomly sampling.
const REPR_SHAVE_BITS: usize = 1;
const REPR_SHAVE_BITS: u32 = 1;
// R = 2**256 % r
const R: FrRepr = FrRepr([0x1fffffffe, 0x5884b7fa00034802, 0x998c4fefecbc4ff5, 0x1824b159acc5056f]);
@ -23,7 +23,7 @@ const INV: u64 = 0xfffffffeffffffff;
const GENERATOR: FrRepr = FrRepr([0xefffffff1, 0x17e363d300189c0f, 0xff9c57876f8457b0, 0x351332208fc5a8c4]);
// 2^s * t = MODULUS - 1 with t odd
const S: usize = 32;
const S: u32 = 32;
// 2^s root of unity computed by GENERATOR^t
const ROOT_OF_UNITY: FrRepr = FrRepr([0xb9b58d8c5f0e466a, 0x5b1b4c801819d7ec, 0xaf53ae352a31e64, 0x5bf3adda19e9b27b]);
@ -114,7 +114,7 @@ impl PrimeFieldRepr for FrRepr {
}
#[inline(always)]
fn divn(&mut self, mut n: usize) {
fn divn(&mut self, mut n: u32) {
if n >= 64 * 4 {
*self = Self::from(0);
return;
@ -161,6 +161,32 @@ impl PrimeFieldRepr for FrRepr {
}
}
#[inline(always)]
fn muln(&mut self, mut n: u32) {
if n >= 64 * 4 {
*self = Self::from(0);
return;
}
while n >= 64 {
let mut t = 0;
for i in &mut self.0 {
::std::mem::swap(&mut t, i);
}
n -= 64;
}
if n > 0 {
let mut t = 0;
for i in &mut self.0 {
let t2 = *i >> (64 - n);
*i <<= n;
*i |= t;
t = t2;
}
}
}
#[inline(always)]
fn num_bits(&self) -> u32 {
let mut ret = (4 as u32) * 64;
@ -264,7 +290,7 @@ impl PrimeField for Fr {
Fr(GENERATOR)
}
fn s() -> usize {
fn s() -> u32 {
S
}
@ -1452,6 +1478,7 @@ fn fr_field_tests() {
::tests::field::random_field_tests::<Fr>();
::tests::field::random_sqrt_tests::<Fr>();
::tests::field::random_frobenius_tests::<Fr, _>(Fr::char(), 13);
::tests::field::from_str_tests::<Fr>();
}
#[test]

View File

@ -11,6 +11,7 @@ mod tests;
pub use self::fr::{Fr, FrRepr};
pub use self::fq::{Fq, FqRepr};
pub use self::fq2::Fq2;
pub use self::fq6::Fq6;
pub use self::fq12::Fq12;
pub use self::ec::{G1, G2, G1Affine, G2Affine, G1Prepared, G2Prepared, G1Uncompressed, G2Uncompressed, G1Compressed, G2Compressed};

View File

@ -9,6 +9,7 @@
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(inline_always))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
#![cfg_attr(feature = "clippy", allow(unreadable_literal))]
// The compiler provides `test` (on nightly) for benchmarking tools, but
// it's hidden behind a feature flag. Enable it if we're testing.
@ -34,21 +35,21 @@ use std::io::{self, Read, Write};
/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
/// with well-defined relationships. In particular, the G1/G2 curve groups are
/// of prime order `r`, and are equipped with a bilinear pairing function.
pub trait Engine {
pub trait Engine: Sized {
/// This is the scalar field of the G1/G2 groups.
type Fr: PrimeField;
/// The projective representation of an element in G1.
type G1: CurveProjective<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.
type G1Affine: CurveAffine<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.
type G2: CurveProjective<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.
type G2Affine: CurveAffine<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.
type Fq: PrimeField + SqrtField;
@ -97,6 +98,7 @@ pub trait CurveProjective: PartialEq +
rand::Rand +
'static
{
type Engine: Engine;
type Scalar: PrimeField;
type Base: SqrtField;
type Affine: CurveAffine<Projective=Self, Scalar=Self::Scalar>;
@ -166,6 +168,7 @@ pub trait CurveAffine: Copy +
Eq +
'static
{
type Engine: Engine;
type Scalar: PrimeField;
type Base: SqrtField;
type Projective: CurveProjective<Affine=Self, Scalar=Self::Scalar>;
@ -352,7 +355,8 @@ pub trait PrimeFieldRepr: Sized +
/// Add another representation to this one, returning the carry bit.
fn add_nocarry(&mut self, other: &Self) -> bool;
/// Compute the number of bits needed to encode this number.
/// Compute the number of bits needed to encode this number. Always a
/// multiple of 64.
fn num_bits(&self) -> u32;
/// Returns true iff this number is zero.
@ -369,12 +373,15 @@ pub trait PrimeFieldRepr: Sized +
fn div2(&mut self);
/// Performs a rightwise bitshift of this number by some amount.
fn divn(&mut self, amt: usize);
fn divn(&mut self, amt: u32);
/// Performs a leftwise bitshift of this number, effectively multiplying
/// it by 2. Overflow is ignored.
fn mul2(&mut self);
/// Performs a leftwise bitshift of this number by some amount.
fn muln(&mut self, amt: u32);
/// Writes this `PrimeFieldRepr` as a big endian integer. Always writes
/// `(num_bits` / 8) bytes.
fn write_be<W: Write>(&self, mut writer: W) -> io::Result<()> {
@ -473,6 +480,46 @@ pub trait PrimeField: Field
/// representation.
type Repr: PrimeFieldRepr + From<Self>;
/// Interpret a string of numbers as a (congruent) prime field element.
/// Does not accept unnecessary leading zeroes or a blank string.
fn from_str(s: &str) -> Option<Self> {
if s.is_empty() {
return None;
}
if s == "0" {
return Some(Self::zero());
}
let mut res = Self::zero();
let ten = Self::from_repr(Self::Repr::from(10)).unwrap();
let mut first_digit = true;
for c in s.chars() {
match c.to_digit(10) {
Some(c) => {
if first_digit {
if c == 0 {
return None;
}
first_digit = false;
}
res.mul_assign(&ten);
res.add_assign(&Self::from_repr(Self::Repr::from(c as u64)).unwrap());
},
None => {
return None;
}
}
}
Some(res)
}
/// Convert this prime field element into a biginteger representation.
fn from_repr(Self::Repr) -> Result<Self, PrimeFieldDecodingError>;
@ -496,7 +543,7 @@ pub trait PrimeField: Field
fn multiplicative_generator() -> Self;
/// Returns s such that 2^s * t = `char()` - 1 with t odd.
fn s() -> usize;
fn s() -> u32;
/// Returns the 2^s root of unity computed by exponentiating the `multiplicative_generator()`
/// by t.

View File

@ -1,5 +1,5 @@
use rand::{Rng, SeedableRng, XorShiftRng};
use ::{SqrtField, Field};
use ::{SqrtField, Field, PrimeField};
pub fn random_frobenius_tests<F: Field, C: AsRef<[u64]>>(characteristic: C, maxpower: usize) {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
@ -87,6 +87,40 @@ pub fn random_field_tests<F: Field>() {
}
}
pub fn from_str_tests<F: PrimeField>() {
{
let a = "84395729384759238745923745892374598234705297301958723458712394587103249587213984572934750213947582345792304758273458972349582734958273495872304598234";
let b = "38495729084572938457298347502349857029384609283450692834058293405982304598230458230495820394850293845098234059823049582309485203948502938452093482039";
let c = "3248875134290623212325429203829831876024364170316860259933542844758450336418538569901990710701240661702808867062612075657861768196242274635305077449545396068598317421057721935408562373834079015873933065667961469731886739181625866970316226171512545167081793907058686908697431878454091011239990119126";
let mut a = F::from_str(a).unwrap();
let b = F::from_str(b).unwrap();
let c = F::from_str(c).unwrap();
a.mul_assign(&b);
assert_eq!(a, c);
}
{
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
let n: u64 = rng.gen();
let a = F::from_str(&format!("{}", n)).unwrap();
let b = F::from_repr(n.into()).unwrap();
assert_eq!(a, b);
}
}
assert!(F::from_str("").is_none());
assert!(F::from_str("0").unwrap().is_zero());
assert!(F::from_str("00").is_none());
assert!(F::from_str("00000000000").is_none());
}
fn random_multiplication_tests<F: Field, R: Rng>(rng: &mut R) {
for _ in 0..10000 {
let a = F::rand(rng);

View File

@ -2,20 +2,64 @@ use rand::{SeedableRng, XorShiftRng};
use ::{PrimeFieldRepr};
pub fn random_repr_tests<R: PrimeFieldRepr>() {
random_encoding_tests::<R>();
random_encoding_tests::<R>();
random_muln_tests::<R>();
random_divn_tests::<R>();
}
fn random_encoding_tests<R: PrimeFieldRepr>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..1000 {
let r = R::rand(&mut rng);
let mut rdecoded = R::default();
for _ in 0..1000 {
let r = R::rand(&mut rng);
let mut rdecoded = R::default();
let mut v: Vec<u8> = vec![];
r.write_be(&mut v).unwrap();
rdecoded.read_be(&v[0..]).unwrap();
let mut v: Vec<u8> = vec![];
r.write_be(&mut v).unwrap();
rdecoded.read_be(&v[0..]).unwrap();
assert_eq!(r, rdecoded);
}
assert_eq!(r, rdecoded);
}
}
fn random_muln_tests<R: PrimeFieldRepr>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..100 {
let r = R::rand(&mut rng);
for shift in 0..(r.num_bits()+1) {
let mut r1 = r;
let mut r2 = r;
for _ in 0..shift {
r1.mul2();
}
r2.muln(shift);
assert_eq!(r1, r2);
}
}
}
fn random_divn_tests<R: PrimeFieldRepr>() {
let mut rng = XorShiftRng::from_seed([0x5dbe6259, 0x8d313d76, 0x3237db17, 0xe5bc0654]);
for _ in 0..100 {
let r = R::rand(&mut rng);
for shift in 0..(r.num_bits()+1) {
let mut r1 = r;
let mut r2 = r;
for _ in 0..shift {
r1.div2();
}
r2.divn(shift);
assert_eq!(r1, r2);
}
}
}