threshold_bls/lib.rs
1//! # Threshold BLS Signatures
2//!
3//! This crate provides implementations for BLS signatures on G1 and G2, with additional support
4//! for blind and threshold signing modes.
5//!
6//! ## Normal BLS Signatures
7//!
8//! ```rust
9//! // import the instantiated scheme and the traits for signing and generating keys
10//! use threshold_bls::{
11//! schemes::bls12_381::G1Scheme as SigScheme,
12//! sig::{Scheme, SignatureScheme}
13//! };
14//!
15//! let (private, public) = SigScheme::keypair(&mut rand::thread_rng());
16//! let msg = b"hello";
17//! let sig = SigScheme::sign(&private, &msg[..]).unwrap();
18//! SigScheme::verify(&public, &msg[..], &sig).expect("signature should be verified");
19//! ```
20//!
21//! ## Blind Signatures
22//!
23//! Blind signatures are supported via an implementation based on this
24//! [paper](https://eprint.iacr.org/2018/733.pdf).
25//!
26//! The procedure is the same, but we import the [`SignatureSchemeExt`] because it requires
27//! signing the blinded message without hashing it. Note that verification is done in the same
28//! way as before on the unblinded signature and message.
29//!
30//! ```rust
31//! // import the instantiated scheme and the traits for signing and generating keys
32//! use threshold_bls::{
33//! schemes::bls12_381::G1Scheme as SigScheme,
34//! sig::{Scheme, SignatureScheme, BlindScheme}
35//! };
36//!
37//! let (private, public) = SigScheme::keypair(&mut rand::thread_rng());
38//! let msg = b"hello";
39//!
40//! // the blinding factor needs to be saved for unblinding later
41//! let (blinding_factor, blinded) = SigScheme::blind_msg(&msg[..], &mut rand::thread_rng());
42//!
43//! // sign the blinded message
44//! let blinded_sig = SigScheme::blind_sign(&private, &blinded).unwrap();
45//! // verify the blinded signature with the blinded message. This can be done
46//! // by any third party given the blinded signature & message, since they are
47//! // not private.
48//! SigScheme::blind_verify(&public, &blinded, &blinded_sig).expect("blinded signature should verify");
49//!
50//! // unblind the signature
51//! let clear_sig = SigScheme::unblind_sig(&blinding_factor, &blinded_sig).expect("unblind should not fail");
52//!
53//! SigScheme::verify(&public, &msg[..], &clear_sig).expect("signature should be verified");
54//! ```
55//!
56//! ## Threshold Signatures
57//!
58//! First a threshold keypair must be generated. This is done utilizing [polynomials](poly).
59//! Each share then proceeds to sign the message, to generate a partial signature. Once enough
60//! partial signatures are produced, they can be combined to a threshold signature, which can be
61//! verified against the threshold public key. Each partial signature can also be individually partially
62//! verified against the public polynomial.
63//!
64//! ```rust
65//! use threshold_bls::{
66//! poly::{Poly, Idx},
67//! schemes::bls12_381::G1Scheme as SigScheme,
68//! sig::{Scheme, SignatureScheme, ThresholdScheme, Share}
69//! };
70//!
71//! let (n, t) = (5, 3);
72//! // create the private key polynomial
73//! let private_poly = Poly::<<SigScheme as Scheme>::Private>::new(t - 1);
74//!
75//! // Evaluate it at `n` points to generate the shares
76//! let shares = (0..n)
77//! .map(|i| {
78//! let eval = private_poly.eval(i as Idx);
79//! Share {
80//! index: eval.index,
81//! private: eval.value,
82//! }
83//! })
84//! .collect::<Vec<_>>();
85//!
86//! // Get the public polynomial
87//! let public_poly = private_poly.commit();
88//! let threshold_public_key = public_poly.public_key();
89//!
90//! // Generate the partial signatures
91//! let msg = b"hello";
92//!
93//! let partials = shares
94//! .iter()
95//! .map(|s| SigScheme::partial_sign(s, &msg[..]).unwrap())
96//! .collect::<Vec<_>>();
97//!
98//! // each partial sig can be partially verified against the public polynomial
99//! partials.iter().for_each(|partial| {
100//! SigScheme::partial_verify(&public_poly, &msg[..], &partial).unwrap();
101//! });
102//!
103//! // generate the threshold sig
104//! let threshold_sig = SigScheme::aggregate(t, &partials).unwrap();
105//!
106//! SigScheme::verify(
107//! &threshold_public_key,
108//! &msg[..],
109//! &threshold_sig
110//! ).unwrap();
111//! ```
112//!
113//!
114//!
115//! # Misc. Notes
116//!
117//! ### Supporting a new curve
118//!
119//! Curves are implemented in the [`curve`] module. In order to support a new curve,
120//! the trait [`PairingCurve`] must be implemented for it. This in turn requires that
121//! you define the pairing-friendly curve's `Scalar` and `G_T` fields, its
122//! G1 and G2 groups and implement the `Scalar`, `Element` and `Point` traits for them.
123//!
124//! ### Switching Groups
125//!
126//! `G1Scheme` can be drop-in replaced with `G2Scheme` (and vice-versa) depending on which group you
127//! want keys and signatures to be in.
128//!
129//! Before:
130//!
131//! ```rust
132//! use threshold_bls::sig::G1Scheme as SigScheme;
133//! ```
134//!
135//! After:
136//!
137//! ```rust
138//! use threshold_bls::sig::G2Scheme as SigScheme;
139//! ```
140//!
141//! ## Features
142//!
143//! Curently there are two curves available, `BLS12 381` and `BN254`. By default they are both
144//! enabled both, but you can select which one you want to use using the features
145//! `bls12_381` and `bn254`.
146//!
147//! You can use them like this when adding the dependency to your `Cargo.toml` file.
148//!
149//! Only BLS12-381:
150//!
151//! ```toml
152//! threshold-bls = { version = "0.1", default-features = false, features = ["bls12_381"] }
153//! ```
154//!
155//! Only BN254:
156//!
157//! ```toml
158//! threshold-bls = { version = "0.1", default-features = false, features = ["bn254"] }
159//! ```
160//!
161//! Both:
162//!
163//! ```toml
164//! threshold-bls = { version = "0.1" }
165//! ```
166//!
167//! [`curve`]: ./curve/index.html
168//! [`SignatureSchemeExt`]: ./sig/trait.SignatureSchemeExt.html
169
170/// Curve implementations for the traits defined in the [`group`](group/index.html) module.
171pub mod curve;
172
173/// Elliptic Curve Integrated Encryption Scheme using SHA256 as the Key Derivation
174pub mod ecies;
175
176/// Definitions of generic traits with scalars of prime fields and points on elliptic curves.
177pub mod group;
178
179/// Implementation of a polynomial suitable to be used for secret sharing schemes and DKG
180/// protocols. It can evaluate and interpolate private and public shares to their corresponding
181/// polynomial.
182pub mod poly;
183
184/// BLS Signature implementations. Supports blind and threshold signatures.
185pub mod sig;
186
187pub mod hash;
188
189pub mod serialize;
190
191/// Pre-instantiated signature schemes for each curve
192pub mod schemes {
193 use crate::sig::{G1Scheme, G2Scheme};
194
195 #[cfg(feature = "bls12_381")]
196 /// BLS12-381 Schemes
197 pub mod bls12_381 {
198 use crate::curve::bls12381::PairingCurve;
199 pub use crate::curve::bls12381::{G1Curve, G2Curve};
200
201 /// Public Keys on G1, Signatures on G2
202 pub type G1Scheme = super::G1Scheme<PairingCurve>;
203 /// Public Keys on G2, Signatures on G1
204 pub type G2Scheme = super::G2Scheme<PairingCurve>;
205 }
206
207 #[cfg(feature = "bn254")]
208 /// BLS12-381 Schemes
209 pub mod bn254 {
210 use crate::curve::bn254::PairingCurve;
211 pub use crate::curve::bn254::{G1Curve, G2Curve};
212
213 /// Public Keys on G1, Signatures on G2
214 pub type G1Scheme = super::G1Scheme<PairingCurve>;
215 /// Public Keys on G2, Signatures on G1
216 pub type G2Scheme = super::G2Scheme<PairingCurve>;
217 }
218}
219
220pub mod test_bls;