commit
24aa1a4052
|
@ -43,8 +43,18 @@ jobs:
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: build
|
command: build
|
||||||
args: --verbose --release --tests
|
args: --verbose --release --tests --features endo
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: test
|
||||||
|
args: --verbose --release --features endo
|
||||||
|
- name: Build tests (no endomorphism)
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --verbose --release --tests
|
||||||
|
- name: Run tests (no endomorphism)
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
|
|
|
@ -6,7 +6,7 @@ homepage = "https://github.com/zkcrypto/bls12_381"
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
name = "bls12_381"
|
name = "bls12_381"
|
||||||
repository = "https://github.com/zkcrypto/bls12_381"
|
repository = "https://github.com/zkcrypto/bls12_381"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
@ -30,3 +30,6 @@ groups = []
|
||||||
pairings = ["groups"]
|
pairings = ["groups"]
|
||||||
alloc = []
|
alloc = []
|
||||||
nightly = ["subtle/nightly"]
|
nightly = ["subtle/nightly"]
|
||||||
|
|
||||||
|
# GLV patents US7110538B2 and US7995752B2 expire in September 2020.
|
||||||
|
endo = []
|
||||||
|
|
|
@ -13,6 +13,7 @@ This crate provides an implementation of the BLS12-381 pairing-friendly elliptic
|
||||||
* `pairings` (on by default): Enables some APIs for performing pairings.
|
* `pairings` (on by default): Enables some APIs for performing pairings.
|
||||||
* `alloc` (on by default): Enables APIs that require an allocator; these include pairing optimizations.
|
* `alloc` (on by default): Enables APIs that require an allocator; these include pairing optimizations.
|
||||||
* `nightly`: Enables `subtle/nightly` which tries to prevent compiler optimizations that could jeopardize constant time operations. Requires the nightly Rust compiler.
|
* `nightly`: Enables `subtle/nightly` which tries to prevent compiler optimizations that could jeopardize constant time operations. Requires the nightly Rust compiler.
|
||||||
|
* `endo`: Enables optimizations that leverage curve endomorphisms, which may run foul of patents US7110538B2 and US7995752B2 set to expire in September 2020.
|
||||||
|
|
||||||
## [Documentation](https://docs.rs/bls12_381)
|
## [Documentation](https://docs.rs/bls12_381)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
# 0.1.1
|
||||||
|
|
||||||
|
Added `clear_cofactor` methods to `G1Projective` and `G2Projective`. If the crate feature `endo`
|
||||||
|
is enabled the G2 cofactor clearing will use the curve endomorphism technique described by
|
||||||
|
[Budroni-Pintore](https://ia.cr/2017/419). If the crate feature `endo` is _not_ enabled then
|
||||||
|
the code will simulate the effects of the Budroni-Pintore cofactor clearing in order to keep
|
||||||
|
the API consistent. In September 2020, when patents US7110538B2 and US7995752B2 expire, the
|
||||||
|
endo feature will be made default. However, for now it must be explicitly enabled.
|
||||||
|
|
||||||
# 0.1.0
|
# 0.1.0
|
||||||
|
|
||||||
Initial release.
|
Initial release.
|
||||||
|
|
36
src/g2.rs
36
src/g2.rs
|
@ -805,7 +805,7 @@ impl G2Projective {
|
||||||
G2Projective::conditional_select(&res, &tmp, (!f1) & (!f2) & (!f3))
|
G2Projective::conditional_select(&res, &tmp, (!f1) & (!f2) & (!f3))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiply(&self, by: &[u8; 32]) -> G2Projective {
|
fn multiply(&self, by: &[u8]) -> G2Projective {
|
||||||
let mut acc = G2Projective::identity();
|
let mut acc = G2Projective::identity();
|
||||||
|
|
||||||
// This is a simple double-and-add implementation of point
|
// This is a simple double-and-add implementation of point
|
||||||
|
@ -827,6 +827,7 @@ impl G2Projective {
|
||||||
acc
|
acc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "endo")]
|
||||||
fn psi(&self) -> G2Projective {
|
fn psi(&self) -> G2Projective {
|
||||||
// 1 / ((u+1) ^ ((q-1)/3))
|
// 1 / ((u+1) ^ ((q-1)/3))
|
||||||
let psi_coeff_x = Fp2 {
|
let psi_coeff_x = Fp2 {
|
||||||
|
@ -870,6 +871,7 @@ impl G2Projective {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "endo")]
|
||||||
fn psi2(&self) -> G2Projective {
|
fn psi2(&self) -> G2Projective {
|
||||||
// 1 / 2 ^ ((q-1)/3)
|
// 1 / 2 ^ ((q-1)/3)
|
||||||
let psi2_coeff_x = Fp2 {
|
let psi2_coeff_x = Fp2 {
|
||||||
|
@ -895,6 +897,7 @@ impl G2Projective {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Multiply `self` by `crate::BLS_X`, using double and add.
|
/// Multiply `self` by `crate::BLS_X`, using double and add.
|
||||||
|
#[cfg(feature = "endo")]
|
||||||
fn mul_by_x(&self) -> G2Projective {
|
fn mul_by_x(&self) -> G2Projective {
|
||||||
let mut xself = G2Projective::identity();
|
let mut xself = G2Projective::identity();
|
||||||
// NOTE: in BLS12-381 we can just skip the first bit.
|
// NOTE: in BLS12-381 we can just skip the first bit.
|
||||||
|
@ -918,15 +921,36 @@ impl G2Projective {
|
||||||
/// This is equivalent to multiplying by $h\_\textrm{eff} = 3(z^2 - 1) \cdot
|
/// This is equivalent to multiplying by $h\_\textrm{eff} = 3(z^2 - 1) \cdot
|
||||||
/// h_2$, where $h_2$ is the cofactor of $\mathbb{G}\_2$ and $z$ is the
|
/// h_2$, where $h_2$ is the cofactor of $\mathbb{G}\_2$ and $z$ is the
|
||||||
/// parameter of BLS12-381.
|
/// parameter of BLS12-381.
|
||||||
|
///
|
||||||
|
/// The endomorphism is only actually used if the crate feature `endo` is
|
||||||
|
/// enabled, and it is disabled by default to mitigate potential patent
|
||||||
|
/// issues.
|
||||||
pub fn clear_cofactor(&self) -> G2Projective {
|
pub fn clear_cofactor(&self) -> G2Projective {
|
||||||
let t1 = self.mul_by_x(); // [x] P
|
#[cfg(feature = "endo")]
|
||||||
let t2 = self.psi(); // psi(P)
|
fn clear_cofactor(this: &G2Projective) -> G2Projective {
|
||||||
|
let t1 = this.mul_by_x(); // [x] P
|
||||||
|
let t2 = this.psi(); // psi(P)
|
||||||
|
|
||||||
self.double().psi2() // psi^2(2P)
|
this.double().psi2() // psi^2(2P)
|
||||||
+ (t1 + t2).mul_by_x() // psi^2(2P) + [x^2] P + [x] psi(P)
|
+ (t1 + t2).mul_by_x() // psi^2(2P) + [x^2] P + [x] psi(P)
|
||||||
- t1 // psi^2(2P) + [x^2 - x] P + [x] psi(P)
|
- t1 // psi^2(2P) + [x^2 - x] P + [x] psi(P)
|
||||||
- t2 // psi^2(2P) + [x^2 - x] P + [x - 1] psi(P)
|
- t2 // psi^2(2P) + [x^2 - x] P + [x - 1] psi(P)
|
||||||
- self // psi^2(2P) + [x^2 - x - 1] P + [x - 1] psi(P)
|
- this // psi^2(2P) + [x^2 - x - 1] P + [x - 1] psi(P)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "endo"))]
|
||||||
|
fn clear_cofactor(this: &G2Projective) -> G2Projective {
|
||||||
|
this.multiply(&[
|
||||||
|
0x51, 0x55, 0xa9, 0xaa, 0x5, 0x0, 0x2, 0xe8, 0xb4, 0xf6, 0xbb, 0xde, 0xa, 0x4c,
|
||||||
|
0x89, 0x59, 0xa3, 0xf6, 0x89, 0x66, 0xc0, 0xcb, 0x54, 0xe9, 0x1a, 0x7c, 0x47, 0xd7,
|
||||||
|
0x69, 0xec, 0xc0, 0x2e, 0xb0, 0x12, 0x12, 0x5d, 0x1, 0xbf, 0x82, 0x6d, 0x95, 0xdb,
|
||||||
|
0x31, 0x87, 0x17, 0x2f, 0x9c, 0x32, 0xe1, 0xff, 0x8, 0x15, 0x3, 0xff, 0x86, 0x99,
|
||||||
|
0x68, 0xd7, 0x5a, 0x14, 0xe9, 0xa8, 0xe2, 0x88, 0x28, 0x35, 0x1b, 0xa9, 0xe, 0x6a,
|
||||||
|
0x4c, 0x58, 0xb3, 0x75, 0xee, 0xf2, 0x8, 0x9f, 0xc6, 0xb,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_cofactor(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a batch of `G2Projective` elements into `G2Affine` elements. This
|
/// Converts a batch of `G2Projective` elements into `G2Affine` elements. This
|
||||||
|
@ -1653,6 +1677,7 @@ fn test_is_torsion_free() {
|
||||||
assert!(bool::from(G2Affine::generator().is_torsion_free()));
|
assert!(bool::from(G2Affine::generator().is_torsion_free()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "endo")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mul_by_x() {
|
fn test_mul_by_x() {
|
||||||
// multiplying by `x` a point in G2 is the same as multiplying by
|
// multiplying by `x` a point in G2 is the same as multiplying by
|
||||||
|
@ -1669,6 +1694,7 @@ fn test_mul_by_x() {
|
||||||
assert_eq!(point.mul_by_x(), point * x);
|
assert_eq!(point.mul_by_x(), point * x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "endo")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_psi() {
|
fn test_psi() {
|
||||||
let generator = G2Projective::generator();
|
let generator = G2Projective::generator();
|
||||||
|
|
Loading…
Reference in New Issue