pairing: Require G1 and G2 to be PrimeCurve

Pairings require that G1, G2, and GT are groups of prime order.
This commit is contained in:
Jack Grigg 2020-08-13 18:11:44 +01:00
parent a6f2172b20
commit 7eaf6493e8
12 changed files with 46 additions and 337 deletions

View File

@ -3,7 +3,7 @@ use std::ops::{AddAssign, MulAssign};
use std::sync::Arc;
use ff::{Field, PrimeField};
use group::{cofactor::CofactorCurveAffine, Curve, Group, Wnaf, WnafGroup};
use group::{prime::PrimeCurveAffine, Curve, Group, Wnaf, WnafGroup};
use pairing::Engine;
use super::{Parameters, VerifyingKey};

View File

@ -2,7 +2,7 @@
//!
//! [Groth16]: https://eprint.iacr.org/2016/260
use group::{cofactor::CofactorCurveAffine, GroupEncoding, UncompressedEncoding};
use group::{prime::PrimeCurveAffine, GroupEncoding, UncompressedEncoding};
use pairing::{Engine, MultiMillerLoop};
use crate::SynthesisError;

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
use futures::Future;
use ff::{Field, PrimeField};
use group::{cofactor::CofactorCurveAffine, Curve};
use group::{prime::PrimeCurveAffine, Curve};
use pairing::Engine;
use super::{ParameterSource, Proof};

View File

@ -1,7 +1,6 @@
use ff::{Field, PrimeField};
use group::{
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
prime::PrimeGroup,
prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup},
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
};
use pairing::{Engine, MillerLoopResult, MultiMillerLoop, PairingCurveAffine};
@ -396,18 +395,6 @@ impl Group for Fr {
impl PrimeGroup for Fr {}
impl CofactorGroup for Fr {
type Subgroup = Fr;
fn clear_cofactor(&self) -> Self::Subgroup {
*self
}
fn into_subgroup(self) -> CtOption<Self::Subgroup> {
CtOption::new(self, Choice::from(1))
}
}
impl Curve for Fr {
type AffineRepr = Fr;
@ -422,7 +409,7 @@ impl WnafGroup for Fr {
}
}
impl CofactorCurve for Fr {
impl PrimeCurve for Fr {
type Affine = Fr;
}
@ -441,7 +428,7 @@ impl AsRef<[u8]> for FakePoint {
}
}
impl CofactorCurveAffine for Fr {
impl PrimeCurveAffine for Fr {
type Curve = Fr;
type Scalar = Fr;

View File

@ -1,4 +1,4 @@
use group::{cofactor::CofactorCurveAffine, Curve};
use group::{prime::PrimeCurveAffine, Curve};
use pairing::{MillerLoopResult, MultiMillerLoop};
use std::ops::{AddAssign, Neg};

View File

@ -2,7 +2,7 @@ use super::multicore::Worker;
use bit_vec::{self, BitVec};
use ff::{Endianness, Field, PrimeField};
use futures::Future;
use group::cofactor::{CofactorCurve, CofactorCurveAffine};
use group::prime::{PrimeCurve, PrimeCurveAffine};
use std::io;
use std::iter;
use std::ops::AddAssign;
@ -11,33 +11,33 @@ use std::sync::Arc;
use super::SynthesisError;
/// An object that builds a source of bases.
pub trait SourceBuilder<G: CofactorCurveAffine>: Send + Sync + 'static + Clone {
pub trait SourceBuilder<G: PrimeCurveAffine>: Send + Sync + 'static + Clone {
type Source: Source<G>;
fn new(self) -> Self::Source;
}
/// A source of bases, like an iterator.
pub trait Source<G: CofactorCurveAffine> {
pub trait Source<G: PrimeCurveAffine> {
fn next(&mut self) -> Result<&G, SynthesisError>;
/// Skips `amt` elements from the source, avoiding deserialization.
fn skip(&mut self, amt: usize) -> Result<(), SynthesisError>;
}
pub trait AddAssignFromSource: CofactorCurve {
pub trait AddAssignFromSource: PrimeCurve {
/// Parses the element from the source. Fails if the point is at infinity.
fn add_assign_from_source<S: Source<<Self as CofactorCurve>::Affine>>(
fn add_assign_from_source<S: Source<<Self as PrimeCurve>::Affine>>(
&mut self,
source: &mut S,
) -> Result<(), SynthesisError> {
AddAssign::<&<Self as CofactorCurve>::Affine>::add_assign(self, source.next()?);
AddAssign::<&<Self as PrimeCurve>::Affine>::add_assign(self, source.next()?);
Ok(())
}
}
impl<G> AddAssignFromSource for G where G: CofactorCurve {}
impl<G> AddAssignFromSource for G where G: PrimeCurve {}
impl<G: CofactorCurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
impl<G: PrimeCurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
type Source = (Arc<Vec<G>>, usize);
fn new(self) -> (Arc<Vec<G>>, usize) {
@ -45,7 +45,7 @@ impl<G: CofactorCurveAffine> SourceBuilder<G> for (Arc<Vec<G>>, usize) {
}
}
impl<G: CofactorCurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
impl<G: PrimeCurveAffine> Source<G> for (Arc<Vec<G>>, usize) {
fn next(&mut self) -> Result<&G, SynthesisError> {
if self.0.len() <= self.1 {
return Err(io::Error::new(
@ -162,8 +162,8 @@ fn multiexp_inner<Q, D, G, S>(
where
for<'a> &'a Q: QueryDensity,
D: Send + Sync + 'static + Clone + AsRef<Q>,
G: CofactorCurve,
S: SourceBuilder<<G as CofactorCurve>::Affine>,
G: PrimeCurve,
S: SourceBuilder<<G as PrimeCurve>::Affine>,
{
// Perform this region of the multiexp
let this = {
@ -274,8 +274,8 @@ pub fn multiexp<Q, D, G, S>(
where
for<'a> &'a Q: QueryDensity,
D: Send + Sync + 'static + Clone + AsRef<Q>,
G: CofactorCurve,
S: SourceBuilder<<G as CofactorCurve>::Affine>,
G: PrimeCurve,
S: SourceBuilder<<G as PrimeCurve>::Affine>,
{
let c = if exponents.len() < 32 {
3u32
@ -296,8 +296,8 @@ where
#[cfg(feature = "pairing")]
#[test]
fn test_with_bls12() {
fn naive_multiexp<G: CofactorCurve>(
bases: Arc<Vec<<G as CofactorCurve>::Affine>>,
fn naive_multiexp<G: PrimeCurve>(
bases: Arc<Vec<<G as PrimeCurve>::Affine>>,
exponents: Arc<Vec<G::Scalar>>,
) -> G {
assert_eq!(bases.len(), exponents.len());

View File

@ -4,12 +4,12 @@ use rand_xorshift::XorShiftRng;
use std::ops::{Mul, Neg};
use crate::{
cofactor::{CofactorCurve, CofactorCurveAffine},
prime::{PrimeCurve, PrimeCurveAffine},
wnaf::WnafGroup,
GroupEncoding, UncompressedEncoding,
};
pub fn curve_tests<G: CofactorCurve>() {
pub fn curve_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -187,7 +187,7 @@ pub fn random_wnaf_tests<G: WnafGroup>() {
}
}
fn random_negation_tests<G: CofactorCurve>() {
fn random_negation_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -217,7 +217,7 @@ fn random_negation_tests<G: CofactorCurve>() {
}
}
fn random_doubling_tests<G: CofactorCurve>() {
fn random_doubling_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -245,7 +245,7 @@ fn random_doubling_tests<G: CofactorCurve>() {
}
}
fn random_multiplication_tests<G: CofactorCurve>() {
fn random_multiplication_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -280,7 +280,7 @@ fn random_multiplication_tests<G: CofactorCurve>() {
}
}
fn random_addition_tests<G: CofactorCurve>() {
fn random_addition_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -360,7 +360,7 @@ fn random_addition_tests<G: CofactorCurve>() {
}
}
fn random_transformation_tests<G: CofactorCurve>() {
fn random_transformation_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -397,7 +397,7 @@ fn random_transformation_tests<G: CofactorCurve>() {
}
}
fn random_compressed_encoding_tests<G: CofactorCurve>() {
fn random_compressed_encoding_tests<G: PrimeCurve>() {
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,
0xe5,
@ -423,9 +423,9 @@ fn random_compressed_encoding_tests<G: CofactorCurve>() {
}
}
pub fn random_uncompressed_encoding_tests<G: CofactorCurve>()
pub fn random_uncompressed_encoding_tests<G: PrimeCurve>()
where
<G as CofactorCurve>::Affine: UncompressedEncoding,
<G as PrimeCurve>::Affine: UncompressedEncoding,
{
let mut rng = XorShiftRng::from_seed([
0x59, 0x62, 0xbe, 0x5d, 0x76, 0x3d, 0x31, 0x8d, 0x17, 0xdb, 0x37, 0x32, 0x54, 0x06, 0xbc,

View File

@ -2,7 +2,6 @@ macro_rules! curve_impl {
(
$name:expr,
$projective:ident,
$subgroup:ident,
$affine:ident,
$basefield:ident,
$scalarfield:ident,
@ -101,21 +100,6 @@ macro_rules! curve_impl {
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct $subgroup($projective);
impl ::std::fmt::Display for $subgroup {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<$subgroup> for $projective {
fn from(val: $subgroup) -> $projective {
val.0
}
}
impl $affine {
fn mul_bits_u64<S: AsRef<[u64]>>(&self, bits: BitIterator<u64, S>) -> $projective {
let mut res = $projective::identity();
@ -213,7 +197,7 @@ macro_rules! curve_impl {
}
}
impl CofactorCurveAffine for $affine {
impl PrimeCurveAffine for $affine {
type Scalar = $scalarfield;
type Curve = $projective;
@ -270,38 +254,6 @@ macro_rules! curve_impl {
}
}
impl GroupEncoding for $subgroup {
type Repr = $compressed;
fn from_bytes(bytes: &Self::Repr) -> CtOption<Self> {
if let Ok(affine) = bytes.into_affine_unchecked() {
// NB: Decompression guarantees that it is on the curve already.
CtOption::new(
$subgroup(affine.into()),
Choice::from(if affine.is_in_correct_subgroup_assuming_on_curve() {
1
} else {
0
}),
)
} else {
CtOption::new(Self::identity(), Choice::from(0))
}
}
fn from_bytes_unchecked(bytes: &Self::Repr) -> CtOption<Self> {
if let Ok(p) = bytes.into_affine_unchecked() {
CtOption::new($subgroup(p.into()), Choice::from(1))
} else {
CtOption::new(Self::identity(), Choice::from(0))
}
}
fn to_bytes(&self) -> Self::Repr {
self.0.to_bytes()
}
}
impl GroupEncoding for $affine {
type Repr = $compressed;
@ -731,181 +683,6 @@ macro_rules! curve_impl {
}
}
impl ::std::iter::Sum for $subgroup {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::identity(), ::std::ops::Add::add)
}
}
impl<'r> ::std::iter::Sum<&'r $subgroup> for $subgroup {
fn sum<I: Iterator<Item = &'r Self>>(iter: I) -> Self {
iter.fold(Self::identity(), ::std::ops::Add::add)
}
}
impl ::std::ops::Neg for $subgroup {
type Output = Self;
#[inline]
fn neg(self) -> Self {
$subgroup(self.0.neg())
}
}
impl<'r> ::std::ops::Add<&'r $subgroup> for $projective {
type Output = Self;
#[inline]
fn add(self, other: &$subgroup) -> Self {
self + &other.0
}
}
impl ::std::ops::Add<$subgroup> for $projective {
type Output = Self;
#[inline]
fn add(self, other: $subgroup) -> Self {
self + &other.0
}
}
impl<'r> ::std::ops::AddAssign<&'r $subgroup> for $projective {
fn add_assign(&mut self, other: &$subgroup) {
self.add_assign(&other.0)
}
}
impl ::std::ops::AddAssign<$subgroup> for $projective {
#[inline]
fn add_assign(&mut self, other: $subgroup) {
self.add_assign(&other.0);
}
}
impl<'r> ::std::ops::Sub<&'r $subgroup> for $projective {
type Output = Self;
#[inline]
fn sub(self, other: &$subgroup) -> Self {
self - &other.0
}
}
impl ::std::ops::Sub<$subgroup> for $projective {
type Output = Self;
#[inline]
fn sub(self, other: $subgroup) -> Self {
self - &other.0
}
}
impl<'r> ::std::ops::SubAssign<&'r $subgroup> for $projective {
fn sub_assign(&mut self, other: &$subgroup) {
self.sub_assign(&other.0);
}
}
impl ::std::ops::SubAssign<$subgroup> for $projective {
#[inline]
fn sub_assign(&mut self, other: $subgroup) {
self.sub_assign(&other.0);
}
}
impl<'r> ::std::ops::Add<&'r $subgroup> for $subgroup {
type Output = Self;
#[inline]
fn add(self, other: &$subgroup) -> Self {
$subgroup(self.0 + &other.0)
}
}
impl ::std::ops::Add<$subgroup> for $subgroup {
type Output = Self;
#[inline]
fn add(self, other: $subgroup) -> Self {
$subgroup(self.0 + &other.0)
}
}
impl<'r> ::std::ops::AddAssign<&'r $subgroup> for $subgroup {
fn add_assign(&mut self, other: &$subgroup) {
self.0.add_assign(&other.0)
}
}
impl ::std::ops::AddAssign<$subgroup> for $subgroup {
#[inline]
fn add_assign(&mut self, other: $subgroup) {
self.0.add_assign(&other.0);
}
}
impl<'r> ::std::ops::Sub<&'r $subgroup> for $subgroup {
type Output = Self;
#[inline]
fn sub(self, other: &$subgroup) -> Self {
$subgroup(self.0 - &other.0)
}
}
impl ::std::ops::Sub<$subgroup> for $subgroup {
type Output = Self;
#[inline]
fn sub(self, other: $subgroup) -> Self {
$subgroup(self.0 - &other.0)
}
}
impl<'r> ::std::ops::SubAssign<&'r $subgroup> for $subgroup {
fn sub_assign(&mut self, other: &$subgroup) {
self.0.sub_assign(&other.0);
}
}
impl ::std::ops::SubAssign<$subgroup> for $subgroup {
#[inline]
fn sub_assign(&mut self, other: $subgroup) {
self.0.sub_assign(&other.0);
}
}
impl ::std::ops::Mul<<$projective as Group>::Scalar> for $subgroup {
type Output = Self;
fn mul(mut self, other: <$projective as Group>::Scalar) -> Self {
self.0.mul_assign(&other);
self
}
}
impl<'r> ::std::ops::Mul<&'r <$projective as Group>::Scalar> for $subgroup {
type Output = Self;
fn mul(mut self, other: &'r <$projective as Group>::Scalar) -> Self {
self.0.mul_assign(other);
self
}
}
impl ::std::ops::MulAssign<<$projective as Group>::Scalar> for $subgroup {
fn mul_assign(&mut self, other: <$projective as Group>::Scalar) {
self.0.mul_assign(&other);
}
}
impl<'r> ::std::ops::MulAssign<&'r <$projective as Group>::Scalar> for $subgroup {
fn mul_assign(&mut self, other: &'r <$projective as Group>::Scalar) {
self.0.mul_assign(other)
}
}
impl Group for $projective {
type Scalar = $scalarfield;
@ -994,55 +771,7 @@ macro_rules! curve_impl {
}
}
impl Group for $subgroup {
type Scalar = $scalarfield;
fn random<R: RngCore + ?Sized>(rng: &mut R) -> Self {
$subgroup($projective::random(rng))
}
fn identity() -> Self {
$subgroup($projective::identity())
}
fn generator() -> Self {
$subgroup($projective::generator())
}
fn is_identity(&self) -> Choice {
self.0.is_identity()
}
#[must_use]
fn double(&self) -> Self {
$subgroup(self.0.double())
}
}
impl PrimeGroup for $subgroup {}
impl CofactorGroup for $projective {
type Subgroup = $subgroup;
fn clear_cofactor(&self) -> Self::Subgroup {
// This implementation uses the cofactor directly, and differs from the
// bls12_381 crate which uses a multiple of the cofactor.
$subgroup($affine::from(*self).scale_by_cofactor().into())
}
fn into_subgroup(self) -> CtOption<Self::Subgroup> {
CtOption::new(
$subgroup(self),
Choice::from(
if $affine::from(self).is_in_correct_subgroup_assuming_on_curve() {
1
} else {
0
},
),
)
}
}
impl PrimeGroup for $projective {}
impl Curve for $projective {
type AffineRepr = $affine;
@ -1102,7 +831,7 @@ macro_rules! curve_impl {
}
}
impl CofactorCurve for $projective {
impl PrimeCurve for $projective {
type Affine = $affine;
}
@ -1206,8 +935,7 @@ pub mod g1 {
use crate::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, PrimeField};
use group::{
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
prime::PrimeGroup,
prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup},
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
};
use rand_core::RngCore;
@ -1218,7 +946,6 @@ pub mod g1 {
curve_impl!(
"G1",
G1,
G1Subgroup,
G1Affine,
Fq,
Fr,
@ -1779,8 +1506,7 @@ pub mod g2 {
use crate::{Engine, PairingCurveAffine};
use ff::{BitIterator, Field, PrimeField};
use group::{
cofactor::{CofactorCurve, CofactorCurveAffine, CofactorGroup},
prime::PrimeGroup,
prime::{PrimeCurve, PrimeCurveAffine, PrimeGroup},
Curve, Group, GroupEncoding, UncompressedEncoding, WnafGroup,
};
use rand_core::RngCore;
@ -1791,7 +1517,6 @@ pub mod g2 {
curve_impl!(
"G2",
G2,
G2Subgroup,
G2Affine,
Fq2,
Fr,

View File

@ -24,7 +24,7 @@ pub use self::fr::{Fr, FrRepr};
use super::{Engine, MillerLoopResult, MultiMillerLoop};
use ff::{BitIterator, Field, PrimeField};
use group::{cofactor::CofactorCurveAffine, Group};
use group::{prime::PrimeCurveAffine, Group};
use rand_core::RngCore;
use std::fmt;
use std::iter::Sum;

View File

@ -1,8 +1,5 @@
use ff::PrimeField;
use group::{
cofactor::{CofactorCurve, CofactorCurveAffine},
GroupEncoding, UncompressedEncoding,
};
use group::{GroupEncoding, UncompressedEncoding};
use super::*;
use crate::*;
@ -58,7 +55,7 @@ fn test_pairing_result_against_relic() {
}));
}
fn uncompressed_test_vectors<G: CofactorCurve>(expected: &[u8])
fn uncompressed_test_vectors<G: PrimeCurve>(expected: &[u8])
where
G::Affine: UncompressedEncoding,
{
@ -88,7 +85,7 @@ where
assert_eq!(&v[..], expected);
}
fn compressed_test_vectors<G: CofactorCurve>(expected: &[u8]) {
fn compressed_test_vectors<G: PrimeCurve>(expected: &[u8]) {
let mut e = G::identity();
let encoded_len = <G::Affine as GroupEncoding>::Repr::default().as_ref().len();

View File

@ -23,7 +23,7 @@ pub mod bls12_381;
use core::ops::Mul;
use ff::PrimeField;
use group::{
cofactor::{CofactorCurve, CofactorCurveAffine},
prime::{PrimeCurve, PrimeCurveAffine},
Group, GroupOps, GroupOpsOwned, ScalarMul, ScalarMulOwned, UncompressedEncoding,
};
@ -35,7 +35,7 @@ pub trait Engine: Sized + 'static + Clone {
type Fr: PrimeField;
/// The projective representation of an element in G1.
type G1: CofactorCurve<Scalar = Self::Fr, Affine = Self::G1Affine>
type G1: PrimeCurve<Scalar = Self::Fr, Affine = Self::G1Affine>
+ From<Self::G1Affine>
+ GroupOps<Self::G1Affine>
+ GroupOpsOwned<Self::G1Affine>
@ -53,7 +53,7 @@ pub trait Engine: Sized + 'static + Clone {
+ for<'a> Mul<&'a Self::Fr, Output = Self::G1>;
/// The projective representation of an element in G2.
type G2: CofactorCurve<Scalar = Self::Fr, Affine = Self::G2Affine>
type G2: PrimeCurve<Scalar = Self::Fr, Affine = Self::G2Affine>
+ From<Self::G2Affine>
+ GroupOps<Self::G2Affine>
+ GroupOpsOwned<Self::G2Affine>
@ -80,7 +80,7 @@ pub trait Engine: Sized + 'static + Clone {
/// Affine representation of an elliptic curve point that can be used
/// to perform pairings.
pub trait PairingCurveAffine: CofactorCurveAffine + UncompressedEncoding {
pub trait PairingCurveAffine: PrimeCurveAffine + UncompressedEncoding {
type Pair: PairingCurveAffine<Pair = Self>;
type PairingResult: Group;

View File

@ -1,5 +1,5 @@
use ff::Field;
use group::{cofactor::CofactorCurveAffine, Curve, Group};
use group::{prime::PrimeCurveAffine, Curve, Group};
use rand_core::SeedableRng;
use rand_xorshift::XorShiftRng;
use std::ops::Mul;