Skip to content

Commit

Permalink
Auto merge of #26 - ebfull:even-more-adjustments, r=ebfull
Browse files Browse the repository at this point in the history
Even more adjustments

Closes #22
Closes #24
Closes #25
  • Loading branch information
bmerge committed Aug 1, 2017
2 parents aa5d634 + 766c902 commit d72929f
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 31 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"

Expand All @@ -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 = []
Expand Down
6 changes: 4 additions & 2 deletions src/bls12_381/ec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ macro_rules! curve_impl {
}

impl CurveAffine for $affine {
type Engine = Bls12;
type Scalar = $scalarfield;
type Base = $basefield;
type Prepared = $prepared;
Expand Down Expand Up @@ -174,6 +175,7 @@ macro_rules! curve_impl {
}

impl CurveProjective for $projective {
type Engine = Bls12;
type Scalar = $scalarfield;
type Base = $basefield;
type Affine = $affine;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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};

Expand Down
35 changes: 31 additions & 4 deletions src/bls12_381/fq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand All @@ -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]);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -444,7 +470,7 @@ impl PrimeField for Fq {
Fq(GENERATOR)
}

fn s() -> usize {
fn s() -> u32 {
S
}

Expand Down Expand Up @@ -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]
Expand Down
35 changes: 31 additions & 4 deletions src/bls12_381/fr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand All @@ -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]);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -264,7 +290,7 @@ impl PrimeField for Fr {
Fr(GENERATOR)
}

fn s() -> usize {
fn s() -> u32 {
S
}

Expand Down Expand Up @@ -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]
Expand Down
1 change: 1 addition & 0 deletions src/bls12_381/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down
63 changes: 55 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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;
Expand Down Expand Up @@ -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>;
Expand Down Expand Up @@ -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>;
Expand Down Expand Up @@ -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.
Expand All @@ -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<()> {
Expand Down Expand Up @@ -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>;

Expand All @@ -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.
Expand Down
36 changes: 35 additions & 1 deletion src/tests/field.rs
Original file line number Diff line number Diff line change
@@ -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]);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit d72929f

Please sign in to comment.