bls_like/
lib.rs

1//! # Aggregate BLS signature library with extensive tuning options. 
2//! 
3//! In short, anyone using BLS signatures should normally choose both
4//! an orientation as well as some aggregation and batching strategies
5//! These two decissions impact performance dramaticaly, but making
6//! the optimal choises requires some attentiom.  This crate employs
7//! convenient abstraction boundaries between curver arithmatic, 
8//! verifier routines, and aggregated and/or batched BLS signatures.
9//! 
10//! ### Pairings
11//! 
12//! If we have two elliptic curve with a pairing `e`, then
13//! a BLS signature `sigma = s*H(msg)` by a public key `S = s g1`
14//! can be verified with the one equation `e(g1,sigma) = e(S,H(msg))`.
15//! These simple BLS signatures are very slow to verify however
16//! because the pairing map `e` is far slower than many cryptographic
17//! primitives.
18//! 
19//! Our pairing `e` maps from a small curve over `F(q)` and a larger
20//! curve over `F(q^2)` into some multipliccative group if a field,
21//! normally over `F(q^12)`.  In principle, this map `e` into `F(q^12)`
22//! makes pairing based cryptography like BLS less secure than
23//! other elliptic curve based cryptography, which further slows down
24//! BLS signatures by requiring larger `q`.
25//!
26//! ### Arithmatic
27//!
28//! An almost universally applicable otimization is to seperate the
29//! "Miller loop" that computes in `F(q)` and `F(q^2)` from the slow
30//! final exponentiation that happens in `F(q^12)`.  So our actual
31//! verification equation more resembles `e(-g1,sigma) e(S,H(msg)) = 1`.
32//!
33//! As one curve is smaller and hence faster, the user should choose 
34//! which orientation of curves they prefer, meaning to which curve
35//! they hash, and which curves hold the signatues and public keys.
36//! In other words, your desired aggregation techniques and usage 
37//! characteristics should determine if youp refer the verification
38//! equation `e(g1,sigma) = e(S,H(msg))` or the fliped form
39//! `e(sigma,g2) = e(H(msg),S)`.  See `UsualBLS` and `TinyBLS`.
40//!
41//! ### Aggregation
42//!
43//! We consder BLS signatures interesting because they support
44//! dramatic optimizations when handling multiple signatures together.
45//! In fact, BLS signatures support aggregation by a third party
46//! that makes signatures smaller, not merely batch verification.  
47//! All this stems from the bilinearity of `e`, meaning we reduce
48//! the number of pairings, or size of the miller loop, by appling
49//! rules like `e(x,z)e(y,z) = e(x+y,z)`, `e(x,y)e(x,z) = e(x,y+z)`,
50//! etc.
51//!
52//! In essence, our aggregation tricks fall into two categories,
53//! linear aggregation, in which only addition is used, and
54//! delinearized optimiztions, in which we multiply curve points
55//! by values unforseeable to the signers.
56//! In general, linear techniques provide much better performance,
57//! but require stronger invariants be maintained by the caller,
58//! like messages being distinct, or limited signer sets with 
59//! proofs-of-possession.  Also, the delinearized techniques remain
60//! secure without tricky assumptions, but require more computation.
61//! 
62//! ### Verification
63//!
64//! We can often further reduce the pairings required in the
65//! verification equation, beyond the naieve information tracked
66//! by the aggregated signature itself.  Aggregated signature must
67//! state all the individual messages and/or public keys, but
68//! verifiers may collapse anything permitted. 
69//! We thus encounter aggregation-like decissions that impact
70//! verifier performance.
71//!
72//! We therefore provide an abstract interface that permits
73//! doing further aggregation and/or passing any aggregate signature
74//! to any verification routine.
75//!
76//! As a rule, we also attempt to batch normalize different arithmatic
77//! outputs, but concievably small signer set sizes might make this
78//! a pessimization.
79//!
80//! 
81//!
82
83
84// #![feature(generic_associated_types)]
85#![feature(associated_type_defaults)]
86
87#[macro_use]
88extern crate arrayref;
89
90// #[macro_use]
91extern crate ff;
92
93extern crate paired as pairing;
94extern crate rand;
95extern crate sha3;
96
97use std::borrow::Borrow;
98
99use ff::{Field, PrimeField, ScalarEngine, SqrtField}; // PrimeFieldDecodingError, PrimeFieldRepr
100use pairing::{CurveAffine, CurveProjective, Engine};
101use rand::{Rand, Rng};
102
103pub mod single;
104pub mod distinct;
105pub mod pop;
106pub mod delinear;
107pub mod verifiers;
108// pub mod delinear;
109
110
111pub use single::{PublicKey,KeypairVT,Keypair,SecretKeyVT,SecretKey,Signature};
112
113
114/// Internal message hash size.  
115///
116/// We choose 256 bits here so that birthday bound attacks cannot
117/// find messages with the same hash.
118const MESSAGE_SIZE: usize = 32;
119
120/// Internal message hash type.  Short for frequent rehashing
121/// by `HashMap`, etc.
122#[derive(Debug,Copy,Clone,Hash,PartialEq,Eq,PartialOrd,Ord)]
123pub struct Message(pub [u8; MESSAGE_SIZE]);
124
125impl Message {
126    pub fn new(context: &'static [u8], message: &[u8]) -> Message {
127        use sha3::{Shake128, digest::{Input,ExtendableOutput,XofReader}};
128        let mut h = Shake128::default();
129        h.input(context);
130        let l = message.len() as u64;
131        h.input(l.to_le_bytes());
132        h.input(message);
133        // let mut t = ::merlin::Transcript::new(context);
134        // t.append_message(b"", message);
135        let mut msg = [0u8; MESSAGE_SIZE];
136        h.xof_result().read(&mut msg[..]);
137        // t.challenge_bytes(b"", &mut msg);
138        Message(msg)
139    }
140
141    pub fn hash_to_signature_curve<E: EngineBLS>(&self) -> E::SignatureGroup {
142        E::hash_to_signature_curve(&self.0[..])
143    }
144}
145
146impl<'a> From<&'a [u8]> for Message {
147    fn from(x: &[u8]) -> Message { Message::new(b"",x) }     
148}
149
150
151/// A weakening of `pairing::Engine` to permit transposing the groups.
152///
153/// You cannot transpose the two groups in a `pairing::Engine` without
154/// first providing panicing implementations of `pairing::PrimeField`
155/// for `Engine::Fqe`, which is not a prime field, and second,
156/// providing wrapper types for the projective and affine group 
157/// representations, which makes interacting with the original
158/// `pairing::Engine` annoying.  This trait merely replicates
159/// transposable functionality from `pairing::Engine` by removing
160/// the fields of definition, but leaves the actual BLS signature
161/// scheme to wrapper types.
162///
163/// We also extract two functions users may with to override:
164/// random scalar generation and hashing to the singature curve.
165pub trait EngineBLS {
166    type Engine: Engine + ScalarEngine<Fr = Self::Scalar>;
167    type Scalar: PrimeField + SqrtField; // = <Self::Engine as ScalarEngine>::Fr;
168
169    /// Group where BLS public keys live
170    /// 
171    /// You should take this to be the `Engine::G1` curve usually
172    /// becuase all verifiers perform additions on this curve, or
173    /// even scalar multiplicaitons with delinearization.
174    type PublicKeyGroup: 
175        CurveProjective<Engine = Self::Engine, Scalar = Self::Scalar>
176        + Into<<Self::PublicKeyGroup as CurveProjective>::Affine>;
177
178    /// Group where BLS signatures live
179    ///
180    /// You should take this to be the `Engine::G2` curve usually
181    /// becuase only aggregators perform additions on this curve, or
182    /// scalar multiplicaitons with delinearization.
183    type SignatureGroup: 
184        CurveProjective<Engine = Self::Engine, Scalar = Self::Scalar>
185        + Into<<Self::SignatureGroup as CurveProjective>::Affine>;
186
187    /// Generate a random scalar for use as a secret key.
188    fn generate<R: Rng>(rng: &mut R) -> Self::Scalar {
189        Self::Scalar::rand(rng)
190    }
191
192    /// Hash one message to the signature curve.
193    fn hash_to_signature_curve<M: Borrow<[u8]>>(message: M) -> Self::SignatureGroup {
194        <Self::SignatureGroup as CurveProjective>::hash(message.borrow())
195    }
196
197    /// Run the Miller loop from `Engine` but orients its arguments
198    /// to be a `SignatureGroup` and `PublicKeyGroup`.
199    fn miller_loop<'a,I>(i: I) -> <Self::Engine as Engine>::Fqk
200    where
201        I: IntoIterator<Item = (
202            &'a <<Self::PublicKeyGroup as CurveProjective>::Affine as CurveAffine>::Prepared,
203            &'a <<Self::SignatureGroup as CurveProjective>::Affine as CurveAffine>::Prepared,
204        )>;
205
206    /// Perform final exponentiation on the result of a Miller loop.
207    fn final_exponentiation(e: &<Self::Engine as Engine>::Fqk) -> Option<<Self::Engine as Engine>::Fqk> {
208        Self::Engine::final_exponentiation(e)
209    }
210
211    /// Performs a pairing operation `e(p, q)` by calling `Engine::pairing`
212    /// but orients its arguments to be a `PublicKeyGroup` and `SignatureGroup`.
213    fn pairing<G1,G2>(p: G1, q: G2) -> <Self::Engine as Engine>::Fqk
214    where
215        G1: Into<<Self::PublicKeyGroup as CurveProjective>::Affine>,
216        G2: Into<<Self::SignatureGroup as CurveProjective>::Affine>;
217    /*
218    {
219        Self::final_exponentiation(&Self::miller_loop(
220            [(&(p.into().prepare()), &(q.into().prepare()))].into_iter(),
221        )).unwrap()
222    }
223    */
224
225    /// Implement verification equation for aggregate BLS signatures
226    /// provided as prepared points
227    /// 
228    /// This low-level routine does no verification of critical security
229    /// properties like message distinctness.  It exists purely to
230    /// simplify replacing mid-level routines with optimized variants,
231    /// like versions that cache public key preperation or use fewer pairings. 
232    fn verify_prepared<'a,I>(
233        signature: &'a <<Self::SignatureGroup as CurveProjective>::Affine as CurveAffine>::Prepared,
234        inputs: I
235      ) -> bool
236    where
237        I: IntoIterator<Item = (
238            &'a <<Self::PublicKeyGroup as CurveProjective>::Affine as CurveAffine>::Prepared,
239            &'a <<Self::SignatureGroup as CurveProjective>::Affine as CurveAffine>::Prepared,
240        )>
241    {
242        // Use a polymorphic static or const if we ever get either. 
243        let mut g1_minus_generator = <Self::PublicKeyGroup as CurveProjective>::Affine::one();
244        g1_minus_generator.negate();
245        Self::final_exponentiation( & Self::miller_loop(
246            inputs.into_iter().map(|t| t)  // reborrow hack
247                .chain(::std::iter::once( (& g1_minus_generator.prepare(), signature) ))
248        ) ).unwrap() == <Self::Engine as Engine>::Fqk::one()
249    }
250}
251
252
253pub type PublicKeyProjective<E> = <E as EngineBLS>::PublicKeyGroup;
254pub type PublicKeyAffine<E> = <<E as EngineBLS>::PublicKeyGroup as CurveProjective>::Affine;
255
256pub type SignatureProjective<E> = <E as EngineBLS>::SignatureGroup;
257pub type SignatureAffine<E> = <<E as EngineBLS>::SignatureGroup as CurveProjective>::Affine;
258
259
260
261
262/// Usual aggregate BLS signature scheme on ZCash's BLS12-381 curve.
263pub type ZBLS = UsualBLS<::pairing::bls12_381::Bls12>;
264
265/// Usual aggregate BLS signature scheme on ZCash's BLS12-381 curve.
266pub const Z_BLS : ZBLS = UsualBLS(::pairing::bls12_381::Bls12);
267
268
269/// Usual BLS variant with tiny 48 byte public keys and 96 byte signatures.
270///
271/// We favor this variant because verifiers always perform
272/// `O(signers)` additions on the `PublicKeyGroup`, or worse 128 bit
273/// scalar multiplications with delinearization. 
274/// We also orient this variant to match zcash's traits.
275#[derive(Default)]
276pub struct UsualBLS<E: Engine>(pub E);
277
278impl<E: Engine> EngineBLS for UsualBLS<E> {
279    type Engine = E;
280    type Scalar = <Self::Engine as ScalarEngine>::Fr;
281    type PublicKeyGroup = E::G1;
282    type SignatureGroup = E::G2;
283
284    fn miller_loop<'a,I>(i: I) -> E::Fqk
285    where
286        I: IntoIterator<Item = (
287            &'a <E::G1Affine as CurveAffine>::Prepared,
288            &'a <E::G2Affine as CurveAffine>::Prepared,
289        )>,
290    {
291        // We require an ugly unecessary allocation here because
292        // zcash's pairing library cnsumes an iterator of references
293        // to tuples of references, which always requires 
294        let i = i.into_iter().map(|t| t)
295              .collect::<Vec<(&<E::G1Affine as CurveAffine>::Prepared,&<E::G2Affine as CurveAffine>::Prepared)>>();
296        E::miller_loop(&i)
297    }
298
299    fn pairing<G1,G2>(p: G1, q: G2) -> E::Fqk
300    where
301        G1: Into<E::G1Affine>,
302        G2: Into<E::G2Affine>,
303    {
304        E::pairing(p,q)
305    }
306}
307
308
309/// Infrequently used BLS variant with tiny 48 byte signatures and 96 byte public keys,
310///
311/// We recommend gainst this variant by default because verifiers
312/// always perform `O(signers)` additions on the `PublicKeyGroup`,
313/// or worse 128 bit scalar multiplications with delinearization. 
314/// Yet, there are specific use cases where this variant performs
315/// better.  We swapy two group roles relative to zcash here.
316#[derive(Default)]
317pub struct TinyBLS<E: Engine>(pub E);
318
319impl<E: Engine> EngineBLS for TinyBLS<E> {
320    type Engine = E;
321    type Scalar = <Self::Engine as ScalarEngine>::Fr;
322    type PublicKeyGroup = E::G2;
323    type SignatureGroup = E::G1;
324
325    fn miller_loop<'a,I>(i: I) -> E::Fqk
326    where
327        I: IntoIterator<Item = (
328            &'a <E::G2Affine as CurveAffine>::Prepared,
329            &'a <E::G1Affine as CurveAffine>::Prepared,
330        )>,
331    {
332        // We require an ugly unecessary allocation here because
333        // zcash's pairing library cnsumes an iterator of references
334        // to tuples of references, which always requires 
335        let i = i.into_iter().map(|(x,y)| (y,x))
336              .collect::<Vec<(&<E::G1Affine as CurveAffine>::Prepared,&<E::G2Affine as CurveAffine>::Prepared)>>();
337        E::miller_loop(&i)
338    }
339
340    fn pairing<G2,G1>(p: G2, q: G1) -> E::Fqk
341    where
342        G1: Into<E::G1Affine>,
343        G2: Into<E::G2Affine>,
344    {
345        E::pairing(q,p)
346    }
347}
348
349
350/// Representation of an aggregated BLS signature.
351///
352/// We implement this trait only for borrows of appropriate structs
353/// because otherwise we'd need extensive lifetime plumbing here,
354/// due to the absence of assocaited type constructers (ATCs).
355/// We shall make `messages_and_publickeys` take `&sefl` and
356/// remove these limitations in the future once ATCs stabalize,
357/// thus removing `PKG`.  See [Rust RFC 1598](https://github.com/rust-lang/rfcs/blob/master/text/1598-generic_associated_types.md)
358/// We shall eventually remove MnPK entirely whenever `-> impl Trait`
359/// in traits gets stabalized.  See [Rust RFCs 1522, 1951, and 2071](https://github.com/rust-lang/rust/issues/34511
360pub trait Signed: Sized {
361    type E: EngineBLS;
362
363    /// Return the aggregated signature 
364    fn signature(&self) -> Signature<Self::E>;
365
366    type M: Borrow<Message> = Message;
367    type PKG: Borrow<PublicKey<Self::E>> = PublicKey<Self::E>;
368
369    /// Iterator over messages and public key reference pairs.
370    type PKnM: Iterator<Item = (Self::M,Self::PKG)> + ExactSizeIterator;
371    // type PKnM<'a>: Iterator<Item = (
372    //    &'a <<Self as Signed<'a>>::E as EngineBLS>::PublicKeyGroup,
373    //    &'a Self::M,
374    // )> + DoubleEndedIterator + ExactSizeIterator + 'a;
375
376    /// Returns an iterator over messages and public key reference for
377    /// pairings, often only partially aggregated. 
378    fn messages_and_publickeys(self) -> Self::PKnM;
379    // fn messages_and_publickeys<'a>(&'s self) -> PKnM<'a>
380    // -> impl Iterator<Item = (&'a Self::M, &'a Self::E::PublicKeyGroup)> + 'a;
381
382    /// Appropriate BLS signature verification for the `Self` type.
383    ///
384    /// We use `verify_simple` as a default implementation because
385    /// it supports unstable `self.messages_and_publickeys()` securely
386    /// by calling it only once, and does not expect pulic key points
387    /// to be normalized, but this should usually be replaced by more
388    /// optimized variants. 
389    fn verify(self) -> bool {
390        verifiers::verify_simple(self)
391    }
392}
393
394
395
396#[cfg(test)]
397mod tests {
398    // use super::*;
399
400    // use rand::{SeedableRng, XorShiftRng};
401
402    // #[test]
403    // fn foo() { }
404}
405