2017-07-16 20:50:03 -07:00
|
|
|
// `clippy` is a code linting tool for improving code quality by catching
|
|
|
|
// common mistakes or strange code patterns. If the `clippy` feature is
|
|
|
|
// provided, it is enabled and all compiler warnings are prohibited.
|
|
|
|
#![cfg_attr(feature = "clippy", deny(warnings))]
|
|
|
|
#![cfg_attr(feature = "clippy", feature(plugin))]
|
|
|
|
#![cfg_attr(feature = "clippy", plugin(clippy))]
|
|
|
|
#![cfg_attr(feature = "clippy", allow(inline_always))]
|
|
|
|
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]
|
2017-08-01 10:37:51 -07:00
|
|
|
#![cfg_attr(feature = "clippy", allow(unreadable_literal))]
|
2018-02-13 08:02:30 -08:00
|
|
|
#![cfg_attr(feature = "clippy", allow(many_single_char_names))]
|
2017-09-28 07:12:37 -07:00
|
|
|
#![cfg_attr(feature = "clippy", allow(new_without_default_derive))]
|
2018-05-17 09:44:28 -07:00
|
|
|
#![cfg_attr(feature = "clippy", allow(write_literal))]
|
2017-09-26 07:59:50 -07:00
|
|
|
// Force public structures to implement Debug
|
|
|
|
#![deny(missing_debug_implementations)]
|
|
|
|
|
2017-07-11 14:01:31 -07:00
|
|
|
extern crate byteorder;
|
2018-06-30 18:56:49 -07:00
|
|
|
extern crate ff;
|
2018-02-21 10:08:58 -08:00
|
|
|
extern crate rand;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
pub mod tests;
|
|
|
|
|
|
|
|
pub mod bls12_381;
|
2017-07-14 10:56:55 -07:00
|
|
|
|
2017-09-27 18:09:59 -07:00
|
|
|
mod wnaf;
|
|
|
|
pub use self::wnaf::Wnaf;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
2018-06-30 23:59:34 -07:00
|
|
|
use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, SqrtField};
|
2017-07-17 08:06:03 -07:00
|
|
|
use std::error::Error;
|
2018-05-17 10:59:20 -07:00
|
|
|
use std::fmt;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// 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.
|
2018-02-21 10:08:58 -08:00
|
|
|
pub trait Engine: Sized + 'static + Clone {
|
2017-07-08 09:55:43 -07:00
|
|
|
/// This is the scalar field of the G1/G2 groups.
|
2017-11-25 19:57:10 -08:00
|
|
|
type Fr: PrimeField + SqrtField;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// The projective representation of an element in G1.
|
2018-02-21 10:08:58 -08:00
|
|
|
type G1: CurveProjective<
|
2018-03-29 10:18:15 -07:00
|
|
|
Engine = Self,
|
|
|
|
Base = Self::Fq,
|
|
|
|
Scalar = Self::Fr,
|
|
|
|
Affine = Self::G1Affine,
|
|
|
|
>
|
2018-02-21 10:08:58 -08:00
|
|
|
+ From<Self::G1Affine>;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// The affine representation of an element in G1.
|
2018-02-21 10:08:58 -08:00
|
|
|
type G1Affine: CurveAffine<
|
2018-03-29 10:18:15 -07:00
|
|
|
Engine = Self,
|
|
|
|
Base = Self::Fq,
|
|
|
|
Scalar = Self::Fr,
|
|
|
|
Projective = Self::G1,
|
|
|
|
Pair = Self::G2Affine,
|
|
|
|
PairingResult = Self::Fqk,
|
|
|
|
>
|
2018-02-21 10:08:58 -08:00
|
|
|
+ From<Self::G1>;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// The projective representation of an element in G2.
|
2018-02-21 10:08:58 -08:00
|
|
|
type G2: CurveProjective<
|
2018-03-29 10:18:15 -07:00
|
|
|
Engine = Self,
|
|
|
|
Base = Self::Fqe,
|
|
|
|
Scalar = Self::Fr,
|
|
|
|
Affine = Self::G2Affine,
|
|
|
|
>
|
2018-02-21 10:08:58 -08:00
|
|
|
+ From<Self::G2Affine>;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// The affine representation of an element in G2.
|
2018-02-21 10:08:58 -08:00
|
|
|
type G2Affine: CurveAffine<
|
2018-03-29 10:18:15 -07:00
|
|
|
Engine = Self,
|
|
|
|
Base = Self::Fqe,
|
|
|
|
Scalar = Self::Fr,
|
|
|
|
Projective = Self::G2,
|
|
|
|
Pair = Self::G1Affine,
|
|
|
|
PairingResult = Self::Fqk,
|
|
|
|
>
|
2018-02-21 10:08:58 -08:00
|
|
|
+ From<Self::G2>;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// The base field that hosts G1.
|
|
|
|
type Fq: PrimeField + SqrtField;
|
|
|
|
|
|
|
|
/// The extension field that hosts G2.
|
|
|
|
type Fqe: SqrtField;
|
|
|
|
|
|
|
|
/// The extension field that hosts the target group of the pairing.
|
|
|
|
type Fqk: Field;
|
|
|
|
|
|
|
|
/// Perform a miller loop with some number of (G1, G2) pairs.
|
|
|
|
fn miller_loop<'a, I>(i: I) -> Self::Fqk
|
2018-02-21 10:08:58 -08:00
|
|
|
where
|
|
|
|
I: IntoIterator<
|
|
|
|
Item = &'a (
|
|
|
|
&'a <Self::G1Affine as CurveAffine>::Prepared,
|
|
|
|
&'a <Self::G2Affine as CurveAffine>::Prepared,
|
|
|
|
),
|
|
|
|
>;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// Perform final exponentiation of the result of a miller loop.
|
|
|
|
fn final_exponentiation(&Self::Fqk) -> Option<Self::Fqk>;
|
|
|
|
|
|
|
|
/// Performs a complete pairing operation `(p, q)`.
|
|
|
|
fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk
|
2018-02-21 10:08:58 -08:00
|
|
|
where
|
|
|
|
G1: Into<Self::G1Affine>,
|
|
|
|
G2: Into<Self::G2Affine>,
|
2017-07-08 09:55:43 -07:00
|
|
|
{
|
|
|
|
Self::final_exponentiation(&Self::miller_loop(
|
2018-02-21 10:08:58 -08:00
|
|
|
[(&(p.into().prepare()), &(q.into().prepare()))].into_iter(),
|
2017-07-08 09:55:43 -07:00
|
|
|
)).unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Projective representation of an elliptic curve point guaranteed to be
|
|
|
|
/// in the correct prime order subgroup.
|
2018-03-29 10:18:15 -07:00
|
|
|
pub trait CurveProjective:
|
|
|
|
PartialEq
|
2018-02-21 10:08:58 -08:00
|
|
|
+ Eq
|
|
|
|
+ Sized
|
|
|
|
+ Copy
|
|
|
|
+ Clone
|
|
|
|
+ Send
|
|
|
|
+ Sync
|
|
|
|
+ fmt::Debug
|
|
|
|
+ fmt::Display
|
|
|
|
+ rand::Rand
|
2018-03-29 10:18:15 -07:00
|
|
|
+ 'static
|
|
|
|
{
|
2018-02-21 10:08:58 -08:00
|
|
|
type Engine: Engine<Fr = Self::Scalar>;
|
2017-11-25 19:57:10 -08:00
|
|
|
type Scalar: PrimeField + SqrtField;
|
2017-07-08 09:55:43 -07:00
|
|
|
type Base: SqrtField;
|
2018-02-21 10:08:58 -08:00
|
|
|
type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// Returns the additive identity.
|
|
|
|
fn zero() -> Self;
|
|
|
|
|
|
|
|
/// Returns a fixed generator of unknown exponent.
|
|
|
|
fn one() -> Self;
|
|
|
|
|
|
|
|
/// Determines if this point is the point at infinity.
|
|
|
|
fn is_zero(&self) -> bool;
|
|
|
|
|
|
|
|
/// Normalizes a slice of projective elements so that
|
|
|
|
/// conversion to affine is cheap.
|
|
|
|
fn batch_normalization(v: &mut [Self]);
|
|
|
|
|
|
|
|
/// Checks if the point is already "normalized" so that
|
|
|
|
/// cheap affine conversion is possible.
|
|
|
|
fn is_normalized(&self) -> bool;
|
|
|
|
|
|
|
|
/// Doubles this element.
|
|
|
|
fn double(&mut self);
|
|
|
|
|
|
|
|
/// Adds another element to this element.
|
|
|
|
fn add_assign(&mut self, other: &Self);
|
|
|
|
|
|
|
|
/// Subtracts another element from this element.
|
|
|
|
fn sub_assign(&mut self, other: &Self) {
|
|
|
|
let mut tmp = *other;
|
|
|
|
tmp.negate();
|
|
|
|
self.add_assign(&tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds an affine element to this element.
|
|
|
|
fn add_assign_mixed(&mut self, other: &Self::Affine);
|
|
|
|
|
|
|
|
/// Negates this element.
|
|
|
|
fn negate(&mut self);
|
|
|
|
|
|
|
|
/// Performs scalar multiplication of this element.
|
|
|
|
fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
|
|
|
|
|
|
|
|
/// Converts this element into its affine representation.
|
2017-07-11 22:37:29 -07:00
|
|
|
fn into_affine(&self) -> Self::Affine;
|
2017-07-09 23:39:38 -07:00
|
|
|
|
2017-09-28 07:38:13 -07:00
|
|
|
/// Recommends a wNAF window table size given a scalar. Always returns a number
|
|
|
|
/// between 2 and 22, inclusive.
|
|
|
|
fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize;
|
2017-07-09 23:39:38 -07:00
|
|
|
|
|
|
|
/// Recommends a wNAF window size given the number of scalars you intend to multiply
|
|
|
|
/// a base by. Always returns a number between 2 and 22, inclusive.
|
|
|
|
fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
|
2017-07-08 09:55:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Affine representation of an elliptic curve point guaranteed to be
|
|
|
|
/// in the correct prime order subgroup.
|
2018-03-29 10:18:15 -07:00
|
|
|
pub trait CurveAffine:
|
|
|
|
Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static
|
|
|
|
{
|
2018-02-21 10:08:58 -08:00
|
|
|
type Engine: Engine<Fr = Self::Scalar>;
|
2017-11-25 19:57:10 -08:00
|
|
|
type Scalar: PrimeField + SqrtField;
|
2017-07-08 09:55:43 -07:00
|
|
|
type Base: SqrtField;
|
2018-02-21 10:08:58 -08:00
|
|
|
type Projective: CurveProjective<Affine = Self, Scalar = Self::Scalar>;
|
2017-07-08 09:55:43 -07:00
|
|
|
type Prepared: Clone + Send + Sync + 'static;
|
2018-02-21 10:08:58 -08:00
|
|
|
type Uncompressed: EncodedPoint<Affine = Self>;
|
|
|
|
type Compressed: EncodedPoint<Affine = Self>;
|
|
|
|
type Pair: CurveAffine<Pair = Self>;
|
2017-07-20 19:52:36 -07:00
|
|
|
type PairingResult: Field;
|
2017-07-08 09:55:43 -07:00
|
|
|
|
|
|
|
/// Returns the additive identity.
|
|
|
|
fn zero() -> Self;
|
|
|
|
|
|
|
|
/// Returns a fixed generator of unknown exponent.
|
|
|
|
fn one() -> Self;
|
|
|
|
|
|
|
|
/// Determines if this point represents the point at infinity; the
|
|
|
|
/// additive identity.
|
|
|
|
fn is_zero(&self) -> bool;
|
|
|
|
|
|
|
|
/// Negates this element.
|
|
|
|
fn negate(&mut self);
|
|
|
|
|
|
|
|
/// Performs scalar multiplication of this element with mixed addition.
|
|
|
|
fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
|
|
|
|
|
|
|
|
/// Prepares this element for pairing purposes.
|
|
|
|
fn prepare(&self) -> Self::Prepared;
|
|
|
|
|
2017-07-20 19:52:36 -07:00
|
|
|
/// Perform a pairing
|
|
|
|
fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
|
|
|
|
|
2017-07-08 09:55:43 -07:00
|
|
|
/// Converts this element into its affine representation.
|
2017-07-11 22:37:29 -07:00
|
|
|
fn into_projective(&self) -> Self::Projective;
|
2017-07-11 14:01:31 -07:00
|
|
|
|
|
|
|
/// Converts this element into its compressed encoding, so long as it's not
|
|
|
|
/// the point at infinity.
|
2017-07-16 19:52:00 -07:00
|
|
|
fn into_compressed(&self) -> Self::Compressed {
|
2017-07-11 14:01:31 -07:00
|
|
|
<Self::Compressed as EncodedPoint>::from_affine(*self)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts this element into its uncompressed encoding, so long as it's not
|
|
|
|
/// the point at infinity.
|
2017-07-16 19:52:00 -07:00
|
|
|
fn into_uncompressed(&self) -> Self::Uncompressed {
|
2017-07-11 14:01:31 -07:00
|
|
|
<Self::Uncompressed as EncodedPoint>::from_affine(*self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`.
|
2018-03-29 10:18:15 -07:00
|
|
|
pub trait EncodedPoint:
|
|
|
|
Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static
|
|
|
|
{
|
2017-07-11 14:01:31 -07:00
|
|
|
type Affine: CurveAffine;
|
|
|
|
|
|
|
|
/// Creates an empty representation.
|
|
|
|
fn empty() -> Self;
|
|
|
|
|
|
|
|
/// Returns the number of bytes consumed by this representation.
|
|
|
|
fn size() -> usize;
|
|
|
|
|
|
|
|
/// Converts an `EncodedPoint` into a `CurveAffine` element,
|
2017-07-17 08:06:03 -07:00
|
|
|
/// if the encoding represents a valid element.
|
|
|
|
fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError>;
|
2017-07-11 14:01:31 -07:00
|
|
|
|
|
|
|
/// Converts an `EncodedPoint` into a `CurveAffine` element,
|
2017-07-17 08:06:03 -07:00
|
|
|
/// without guaranteeing that the encoding represents a valid
|
|
|
|
/// element. This is useful when the caller knows the encoding is
|
|
|
|
/// valid already.
|
|
|
|
///
|
|
|
|
/// If the encoding is invalid, this can break API invariants,
|
|
|
|
/// so caution is strongly encouraged.
|
|
|
|
fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError>;
|
2017-07-11 14:01:31 -07:00
|
|
|
|
|
|
|
/// Creates an `EncodedPoint` from an affine point, as long as the
|
|
|
|
/// point is not the point at infinity.
|
2017-07-16 19:52:00 -07:00
|
|
|
fn from_affine(affine: Self::Affine) -> Self;
|
2017-07-08 09:55:43 -07:00
|
|
|
}
|
|
|
|
|
2017-07-17 11:24:00 -07:00
|
|
|
/// An error that may occur when trying to decode an `EncodedPoint`.
|
2017-07-17 08:06:03 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum GroupDecodingError {
|
|
|
|
/// The coordinate(s) do not lie on the curve.
|
|
|
|
NotOnCurve,
|
|
|
|
/// The element is not part of the r-order subgroup.
|
|
|
|
NotInSubgroup,
|
|
|
|
/// One of the coordinates could not be decoded
|
|
|
|
CoordinateDecodingError(&'static str, PrimeFieldDecodingError),
|
2017-08-14 01:46:55 -07:00
|
|
|
/// The compression mode of the encoded element was not as expected
|
2017-07-17 08:06:03 -07:00
|
|
|
UnexpectedCompressionMode,
|
|
|
|
/// The encoding contained bits that should not have been set
|
2018-02-21 10:08:58 -08:00
|
|
|
UnexpectedInformation,
|
2017-07-17 08:06:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Error for GroupDecodingError {
|
|
|
|
fn description(&self) -> &str {
|
2017-07-18 09:16:49 -07:00
|
|
|
match *self {
|
|
|
|
GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
|
|
|
|
GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
|
|
|
|
GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
|
2018-02-21 10:08:58 -08:00
|
|
|
GroupDecodingError::UnexpectedCompressionMode => {
|
|
|
|
"encoding has unexpected compression mode"
|
|
|
|
}
|
|
|
|
GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
|
2017-07-17 08:06:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for GroupDecodingError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
2017-07-18 09:16:49 -07:00
|
|
|
match *self {
|
|
|
|
GroupDecodingError::CoordinateDecodingError(description, ref err) => {
|
2017-07-17 08:06:03 -07:00
|
|
|
write!(f, "{} decoding error: {}", description, err)
|
|
|
|
}
|
2018-02-21 10:08:58 -08:00
|
|
|
_ => write!(f, "{}", self.description()),
|
2017-07-17 08:06:03 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|