Skip to content

Commit

Permalink
Merge pull request #245 from str4d/impl-group-pairing-traits
Browse files Browse the repository at this point in the history
Implement group and pairing traits for bls12_381 and jubjub crates
  • Loading branch information
str4d authored Aug 19, 2020
2 parents b86558c + 3200ffc commit 544d593
Show file tree
Hide file tree
Showing 12 changed files with 1,203 additions and 13 deletions.
15 changes: 13 additions & 2 deletions bls12_381/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ path = "../ff"
version = "0.6"
default-features = false

[dependencies.group]
path = "../group"
version = "0.6"
default-features = false
optional = true

[dependencies.pairing]
path = "../pairing"
version = "0.16"
optional = true

[dependencies.rand_core]
version = "0.5"
default-features = false
Expand All @@ -39,8 +50,8 @@ default-features = false

[features]
default = ["groups", "pairings", "alloc"]
groups = []
pairings = ["groups"]
groups = ["group"]
pairings = ["groups", "pairing"]
alloc = []
nightly = ["subtle/nightly"]

Expand Down
54 changes: 53 additions & 1 deletion bls12_381/src/fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use core::convert::TryFrom;
use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};

use rand_core::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

use crate::util::{adc, mac, sbb};
Expand Down Expand Up @@ -97,6 +97,16 @@ const R2: Fp = Fp([
0x1198_8fe5_92ca_e3aa,
]);

/// R3 = 2^(384*3) mod p
const R3: Fp = Fp([
0xed48_ac6b_d94c_a1e0,
0x315f_831e_03a7_adf8,
0x9a53_352a_615e_29dd,
0x34c0_4e5e_921e_1761,
0x2512_d435_6572_4728,
0x0aa6_3460_9175_5d4d,
]);

impl<'a> Neg for &'a Fp {
type Output = Fp;

Expand Down Expand Up @@ -214,6 +224,48 @@ impl Fp {
res
}

pub(crate) fn random<R: RngCore + ?Sized>(rng: &mut R) -> Fp {
let mut bytes = [0u8; 96];
rng.fill_bytes(&mut bytes);

// Parse the random bytes as a big-endian number, to match Fp encoding order.
Fp::from_u768([
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[0..8]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[8..16]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[16..24]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[24..32]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[32..40]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[40..48]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[48..56]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[56..64]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[64..72]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[72..80]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[80..88]).unwrap()),
u64::from_be_bytes(<[u8; 8]>::try_from(&bytes[88..96]).unwrap()),
])
}

/// Reduces a big-endian 64-bit limb representation of a 768-bit number.
fn from_u768(limbs: [u64; 12]) -> Fp {
// We reduce an arbitrary 768-bit number by decomposing it into two 384-bit digits
// with the higher bits multiplied by 2^384. Thus, we perform two reductions
//
// 1. the lower bits are multiplied by R^2, as normal
// 2. the upper bits are multiplied by R^2 * 2^384 = R^3
//
// and computing their sum in the field. It remains to see that arbitrary 384-bit
// numbers can be placed into Montgomery form safely using the reduction. The
// reduction works so long as the product is less than R=2^384 multiplied by
// the modulus. This holds because for any `c` smaller than the modulus, we have
// that (2^384 - 1)*c is an acceptable product for the reduction. Therefore, the
// reduction always works so long as `c` is in the field; in this case it is either the
// constant `R2` or `R3`.
let d1 = Fp([limbs[11], limbs[10], limbs[9], limbs[8], limbs[7], limbs[6]]);
let d0 = Fp([limbs[5], limbs[4], limbs[3], limbs[2], limbs[1], limbs[0]]);
// Convert to Montgomery form
d0 * R2 + d1 * R3
}

/// Returns whether or not this element is strictly lexicographically
/// larger than its negation.
pub fn lexicographically_largest(&self) -> Choice {
Expand Down
8 changes: 8 additions & 0 deletions bls12_381/src/fp12.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::fp6::*;

use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use rand_core::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

/// This represents an element $c_0 + c_1 w$ of $\mathbb{F}_{p^12} = \mathbb{F}_{p^6} / w^2 - v$.
Expand Down Expand Up @@ -99,6 +100,13 @@ impl Fp12 {
}
}

pub(crate) fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
Fp12 {
c0: Fp6::random(rng),
c1: Fp6::random(rng),
}
}

pub fn mul_by_014(&self, c0: &Fp2, c1: &Fp2, c4: &Fp2) -> Fp12 {
let aa = self.c0.mul_by_01(c0, c1);
let bb = self.c1.mul_by_1(c4);
Expand Down
9 changes: 8 additions & 1 deletion bls12_381/src/fp2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};

use rand_core::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

use crate::fp::Fp;
Expand Down Expand Up @@ -126,6 +126,13 @@ impl Fp2 {
self.c0.is_zero() & self.c1.is_zero()
}

pub(crate) fn random<R: RngCore + ?Sized>(rng: &mut R) -> Fp2 {
Fp2 {
c0: Fp::random(rng),
c1: Fp::random(rng),
}
}

/// Raises this element to p.
#[inline(always)]
pub fn frobenius_map(&self) -> Self {
Expand Down
9 changes: 9 additions & 0 deletions bls12_381/src/fp6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::fp2::*;

use core::fmt;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use rand_core::RngCore;
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};

/// This represents an element $c_0 + c_1 v + c_2 v^2$ of $\mathbb{F}_{p^6} = \mathbb{F}_{p^2} / v^3 - u - 1$.
Expand Down Expand Up @@ -95,6 +96,14 @@ impl Fp6 {
}
}

pub(crate) fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
Fp6 {
c0: Fp2::random(rng),
c1: Fp2::random(rng),
c2: Fp2::random(rng),
}
}

pub fn mul_by_1(&self, c1: &Fp2) -> Fp6 {
let b_b = self.c1 * c1;

Expand Down
Loading

0 comments on commit 544d593

Please sign in to comment.