Add implementation of q-order subgroup checking for G1Affine/G2Affine.

This commit is contained in:
Sean Bowe 2019-08-11 20:04:52 -06:00
parent 526209abdf
commit b893a04fbe
No known key found for this signature in database
GPG Key ID: 95684257D8F8B031
3 changed files with 110 additions and 0 deletions

View File

@ -21,6 +21,9 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function(&format!("{} scalar multiplication", name), move |b| {
b.iter(|| black_box(a) * black_box(s))
});
c.bench_function(&format!("{} subgroup check", name), move |b| {
b.iter(|| black_box(a).is_torsion_free())
});
}
// G1Projective
@ -66,6 +69,9 @@ fn criterion_benchmark(c: &mut Criterion) {
c.bench_function(&format!("{} scalar multiplication", name), move |b| {
b.iter(|| black_box(a) * black_box(s))
});
c.bench_function(&format!("{} subgroup check", name), move |b| {
b.iter(|| black_box(a).is_torsion_free())
});
}
// G2Projective

View File

@ -186,6 +186,21 @@ impl G1Affine {
self.infinity
}
/// Returns true if this point is free of an $h$-torsion component, and so it
/// exists within the $q$-order subgroup $\mathbb{G}_1$. This should always return true
/// unless an "unchecked" API was used.
pub fn is_torsion_free(&self) -> Choice {
const FQ_MODULUS_BYTES: [u8; 32] = [
1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115,
];
// Clear the r-torsion from the point and check if it is the identity
G1Projective::from(*self)
.multiply(&FQ_MODULUS_BYTES)
.is_identity()
}
/// Returns true if this point is on the curve. This should always return
/// true unless an "unchecked" API was used.
pub fn is_on_curve(&self) -> Choice {
@ -1041,3 +1056,30 @@ fn test_affine_scalar_multiplication() {
assert_eq!(G1Affine::from(g * a) * b, g * c);
}
#[test]
fn test_is_torsion_free() {
let a = G1Affine {
x: Fp::from_raw_unchecked([
0xabaf895b97e43c8,
0xba4c6432eb9b61b0,
0x12506f52adfe307f,
0x75028c3439336b72,
0x84744f05b8e9bd71,
0x113d554fb09554f7,
]),
y: Fp::from_raw_unchecked([
0x73e90e88f5cf01c0,
0x37007b65dd3197e2,
0x5cf9a1992f0d7c78,
0x4f83c10b9eb3330d,
0xf6a63f6f07f60961,
0xc53b5b97e634df3,
]),
infinity: Choice::from(0u8),
};
assert!(!bool::from(a.is_torsion_free()));
assert!(bool::from(G1Affine::identity().is_torsion_free()));
assert!(bool::from(G1Affine::generator().is_torsion_free()));
}

View File

@ -217,6 +217,21 @@ impl G2Affine {
self.infinity
}
/// Returns true if this point is free of an $h$-torsion component, and so it
/// exists within the $q$-order subgroup $\mathbb{G}_2$. This should always return true
/// unless an "unchecked" API was used.
pub fn is_torsion_free(&self) -> Choice {
const FQ_MODULUS_BYTES: [u8; 32] = [
1, 0, 0, 0, 255, 255, 255, 255, 254, 91, 254, 255, 2, 164, 189, 83, 5, 216, 161, 9, 8,
216, 57, 51, 72, 125, 157, 41, 83, 167, 237, 115,
];
// Clear the r-torsion from the point and check if it is the identity
G2Projective::from(*self)
.multiply(&FQ_MODULUS_BYTES)
.is_identity()
}
/// Returns true if this point is on the curve. This should always return
/// true unless an "unchecked" API was used.
pub fn is_on_curve(&self) -> Choice {
@ -1228,3 +1243,50 @@ fn test_affine_scalar_multiplication() {
assert_eq!(G2Affine::from(g * a) * b, g * c);
}
#[test]
fn test_is_torsion_free() {
let a = G2Affine {
x: Fp2 {
c0: Fp::from_raw_unchecked([
0x89f550c813db6431,
0xa50be8c456cd8a1a,
0xa45b374114cae851,
0xbb6190f5bf7fff63,
0x970ca02c3ba80bc7,
0x2b85d24e840fbac,
]),
c1: Fp::from_raw_unchecked([
0x6888bc53d70716dc,
0x3dea6b4117682d70,
0xd8f5f930500ca354,
0x6b5ecb6556f5c155,
0xc96bef0434778ab0,
0x5081505515006ad,
]),
},
y: Fp2 {
c0: Fp::from_raw_unchecked([
0x3cf1ea0d434b0f40,
0x1a0dc610e603e333,
0x7f89956160c72fa0,
0x25ee03decf6431c5,
0xeee8e206ec0fe137,
0x97592b226dfef28,
]),
c1: Fp::from_raw_unchecked([
0x71e8bb5f29247367,
0xa5fe049e211831ce,
0xce6b354502a3896,
0x93b012000997314e,
0x6759f3b6aa5b42ac,
0x156944c4dfe92bbb,
]),
},
infinity: Choice::from(0u8),
};
assert!(!bool::from(a.is_torsion_free()));
assert!(bool::from(G2Affine::identity().is_torsion_free()));
assert!(bool::from(G2Affine::generator().is_torsion_free()));
}