Skip to main content

fawkes_crypto_pairing_ce/
lib.rs

1// `clippy` is a code linting tool for improving code quality by catching
2// common mistakes or strange code patterns. If the `cargo-clippy` feature
3// is provided, all compiler warnings are prohibited.
4#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
5// #![cfg_attr(feature = "cargo-clippy", allow(inline_always))]
6// #![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
7// #![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
8// #![cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
9// #![cfg_attr(feature = "cargo-clippy", allow(new_without_default_derive))]
10// #![cfg_attr(feature = "cargo-clippy", allow(write_literal))]
11// Force public structures to implement Debug
12#![deny(missing_debug_implementations)]
13
14extern crate byteorder;
15extern crate rand;
16
17#[cfg(test)]
18pub mod tests;
19
20pub extern crate ff;
21
22pub use ff::*;
23
24pub mod bls12_381;
25pub mod bn256;
26
27mod wnaf;
28pub use self::wnaf::Wnaf;
29
30use ff::{Field, PrimeField, PrimeFieldDecodingError, PrimeFieldRepr, ScalarEngine, SqrtField};
31use std::error::Error;
32use std::fmt;
33
34/// An "engine" is a collection of types (fields, elliptic curve groups, etc.)
35/// with well-defined relationships. In particular, the G1/G2 curve groups are
36/// of prime order `r`, and are equipped with a bilinear pairing function.
37pub trait Engine: ScalarEngine {
38    /// The projective representation of an element in G1.
39    type G1: CurveProjective<
40            Engine = Self,
41            Base = Self::Fq,
42            Scalar = Self::Fr,
43            Affine = Self::G1Affine,
44        >
45        + From<Self::G1Affine>;
46
47    /// The affine representation of an element in G1.
48    type G1Affine: CurveAffine<
49            Engine = Self,
50            Base = Self::Fq,
51            Scalar = Self::Fr,
52            Projective = Self::G1,
53            Pair = Self::G2Affine,
54            PairingResult = Self::Fqk,
55        >
56        + From<Self::G1> + RawEncodable;
57
58    /// The projective representation of an element in G2.
59    type G2: CurveProjective<
60            Engine = Self,
61            Base = Self::Fqe,
62            Scalar = Self::Fr,
63            Affine = Self::G2Affine,
64        >
65        + From<Self::G2Affine>;
66
67    /// The affine representation of an element in G2.
68    type G2Affine: CurveAffine<
69            Engine = Self,
70            Base = Self::Fqe,
71            Scalar = Self::Fr,
72            Projective = Self::G2,
73            Pair = Self::G1Affine,
74            PairingResult = Self::Fqk,
75        >
76        + From<Self::G2> + RawEncodable;
77
78    /// The base field that hosts G1.
79    type Fq: PrimeField + SqrtField;
80
81    /// The extension field that hosts G2.
82    type Fqe: SqrtField;
83
84    /// The extension field that hosts the target group of the pairing.
85    type Fqk: Field;
86
87    /// Perform a miller loop with some number of (G1, G2) pairs.
88    fn miller_loop<'a, I>(i: I) -> Self::Fqk
89    where
90        I: IntoIterator<
91            Item = &'a (
92                &'a <Self::G1Affine as CurveAffine>::Prepared,
93                &'a <Self::G2Affine as CurveAffine>::Prepared,
94            ),
95        >;
96
97    /// Perform final exponentiation of the result of a miller loop.
98    fn final_exponentiation(r: &Self::Fqk) -> Option<Self::Fqk>;
99
100    /// Performs a complete pairing operation `(p, q)`.
101    fn pairing<G1, G2>(p: G1, q: G2) -> Self::Fqk
102    where
103        G1: Into<Self::G1Affine>,
104        G2: Into<Self::G2Affine>,
105    {
106        Self::final_exponentiation(&Self::miller_loop(
107            [(&(p.into().prepare()), &(q.into().prepare()))].iter(),
108        )).unwrap()
109    }
110}
111
112/// Projective representation of an elliptic curve point guaranteed to be
113/// in the correct prime order subgroup.
114pub trait CurveProjective:
115    PartialEq
116    + Eq
117    + Sized
118    + Copy
119    + Clone
120    + Send
121    + Sync
122    + fmt::Debug
123    + fmt::Display
124    + rand::Rand
125    + 'static
126{
127    type Engine: Engine<Fr = Self::Scalar>;
128    type Scalar: PrimeField + SqrtField;
129    type Base: SqrtField;
130    type Affine: CurveAffine<Projective = Self, Scalar = Self::Scalar>;
131
132    /// Returns the additive identity.
133    fn zero() -> Self;
134
135    /// Returns a fixed generator of unknown exponent.
136    fn one() -> Self;
137
138    /// Determines if this point is the point at infinity.
139    fn is_zero(&self) -> bool;
140
141    /// Normalizes a slice of projective elements so that
142    /// conversion to affine is cheap.
143    fn batch_normalization(v: &mut [Self]);
144
145    /// Checks if the point is already "normalized" so that
146    /// cheap affine conversion is possible.
147    fn is_normalized(&self) -> bool;
148
149    /// Doubles this element.
150    fn double(&mut self);
151
152    /// Adds another element to this element.
153    fn add_assign(&mut self, other: &Self);
154
155    /// Subtracts another element from this element.
156    fn sub_assign(&mut self, other: &Self) {
157        let mut tmp = *other;
158        tmp.negate();
159        self.add_assign(&tmp);
160    }
161
162    /// Adds an affine element to this element.
163    fn add_assign_mixed(&mut self, other: &Self::Affine);
164
165    /// Negates this element.
166    fn negate(&mut self);
167
168    /// Performs scalar multiplication of this element.
169    fn mul_assign<S: Into<<Self::Scalar as PrimeField>::Repr>>(&mut self, other: S);
170
171    /// Converts this element into its affine representation.
172    fn into_affine(&self) -> Self::Affine;
173
174    /// Recommends a wNAF window table size given a scalar. Always returns a number
175    /// between 2 and 22, inclusive.
176    fn recommended_wnaf_for_scalar(scalar: <Self::Scalar as PrimeField>::Repr) -> usize;
177
178    /// Recommends a wNAF window size given the number of scalars you intend to multiply
179    /// a base by. Always returns a number between 2 and 22, inclusive.
180    fn recommended_wnaf_for_num_scalars(num_scalars: usize) -> usize;
181}
182
183/// Affine representation of an elliptic curve point guaranteed to be
184/// in the correct prime order subgroup.
185pub trait CurveAffine:
186    Copy + Clone + Sized + Send + Sync + fmt::Debug + fmt::Display + PartialEq + Eq + 'static
187{
188    type Engine: Engine<Fr = Self::Scalar>;
189    type Scalar: PrimeField + SqrtField;
190    type Base: SqrtField;
191    type Projective: CurveProjective<Affine = Self, Scalar = Self::Scalar>;
192    type Prepared: Clone + Send + Sync + 'static;
193    type Uncompressed: EncodedPoint<Affine = Self>;
194    type Compressed: EncodedPoint<Affine = Self>;
195    type Pair: CurveAffine<Pair = Self>;
196    type PairingResult: Field;
197
198    /// Returns the additive identity.
199    fn zero() -> Self;
200
201    /// Returns a fixed generator of unknown exponent.
202    fn one() -> Self;
203
204    /// Determines if this point represents the point at infinity; the
205    /// additive identity.
206    fn is_zero(&self) -> bool;
207
208    /// Negates this element.
209    fn negate(&mut self);
210
211    /// Performs scalar multiplication of this element with mixed addition.
212    fn mul<S: Into<<Self::Scalar as PrimeField>::Repr>>(&self, other: S) -> Self::Projective;
213
214    /// Prepares this element for pairing purposes.
215    fn prepare(&self) -> Self::Prepared;
216
217    /// Perform a pairing
218    fn pairing_with(&self, other: &Self::Pair) -> Self::PairingResult;
219
220    /// Converts this element into its affine representation.
221    fn into_projective(&self) -> Self::Projective;
222
223    /// Converts this element into its compressed encoding, so long as it's not
224    /// the point at infinity.
225    fn into_compressed(&self) -> Self::Compressed {
226        <Self::Compressed as EncodedPoint>::from_affine(*self)
227    }
228
229    /// Converts this element into its uncompressed encoding, so long as it's not
230    /// the point at infinity.
231    fn into_uncompressed(&self) -> Self::Uncompressed {
232        <Self::Uncompressed as EncodedPoint>::from_affine(*self)
233    }
234}
235
236pub trait RawEncodable: CurveAffine {
237    /// Converts this element into its uncompressed encoding, so long as it's not
238    /// the point at infinity. Leaves coordinates in Montgommery form
239    fn into_raw_uncompressed_le(&self) -> Self::Uncompressed;
240
241    /// Creates a point from raw encoded coordinates without checking on curve
242    fn from_raw_uncompressed_le_unchecked(encoded: &Self::Uncompressed, infinity: bool) -> Result<Self, GroupDecodingError>;
243
244    /// Creates a point from raw encoded coordinates
245    fn from_raw_uncompressed_le(encoded: &Self::Uncompressed, infinity: bool) -> Result<Self, GroupDecodingError>;
246}
247
248/// An encoded elliptic curve point, which should essentially wrap a `[u8; N]`.
249pub trait EncodedPoint:
250    Sized + Send + Sync + AsRef<[u8]> + AsMut<[u8]> + Clone + Copy + 'static
251{
252    type Affine: CurveAffine;
253
254    /// Creates an empty representation.
255    fn empty() -> Self;
256
257    /// Returns the number of bytes consumed by this representation.
258    fn size() -> usize;
259
260    /// Converts an `EncodedPoint` into a `CurveAffine` element,
261    /// if the encoding represents a valid element.
262    fn into_affine(&self) -> Result<Self::Affine, GroupDecodingError>;
263
264    /// Converts an `EncodedPoint` into a `CurveAffine` element,
265    /// without guaranteeing that the encoding represents a valid
266    /// element. This is useful when the caller knows the encoding is
267    /// valid already.
268    ///
269    /// If the encoding is invalid, this can break API invariants,
270    /// so caution is strongly encouraged.
271    fn into_affine_unchecked(&self) -> Result<Self::Affine, GroupDecodingError>;
272
273    /// Creates an `EncodedPoint` from an affine point, as long as the
274    /// point is not the point at infinity.
275    fn from_affine(affine: Self::Affine) -> Self;
276}
277
278/// An error that may occur when trying to decode an `EncodedPoint`.
279#[derive(Debug)]
280pub enum GroupDecodingError {
281    /// The coordinate(s) do not lie on the curve.
282    NotOnCurve,
283    /// The element is not part of the r-order subgroup.
284    NotInSubgroup,
285    /// One of the coordinates could not be decoded
286    CoordinateDecodingError(&'static str, PrimeFieldDecodingError),
287    /// The compression mode of the encoded element was not as expected
288    UnexpectedCompressionMode,
289    /// The encoding contained bits that should not have been set
290    UnexpectedInformation,
291}
292
293impl Error for GroupDecodingError {
294    fn description(&self) -> &str {
295        match *self {
296            GroupDecodingError::NotOnCurve => "coordinate(s) do not lie on the curve",
297            GroupDecodingError::NotInSubgroup => "the element is not part of an r-order subgroup",
298            GroupDecodingError::CoordinateDecodingError(..) => "coordinate(s) could not be decoded",
299            GroupDecodingError::UnexpectedCompressionMode => {
300                "encoding has unexpected compression mode"
301            }
302            GroupDecodingError::UnexpectedInformation => "encoding has unexpected information",
303        }
304    }
305}
306
307impl fmt::Display for GroupDecodingError {
308    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
309        match *self {
310            GroupDecodingError::CoordinateDecodingError(description, ref err) => {
311                write!(f, "{} decoding error: {}", description, err)
312            }
313            _ => write!(f, "{}", self.to_string()),
314        }
315    }
316}