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

/// Curve implementations for the traits defined in the [`group`](group/index.html) module.
pub mod curve;

/// Elliptic Curve Integrated Encryption Scheme using SHA256 as the Key Derivation
pub mod ecies;

/// Definitions of generic traits with scalars of prime fields and points on elliptic curves.
pub mod group;

/// Implementation of a polynomial suitable to be used for secret sharing schemes and DKG
/// protocols. It can evaluate and interpolate private and public shares to their corresponding
/// polynomial.
pub mod poly;

/// BLS Signature implementations. Supports blind and threshold signatures.
pub mod sig;

pub mod hash;

pub mod serialize;

/// Pre-instantiated signature schemes for each curve
pub mod schemes {
    use crate::sig::{G1Scheme, G2Scheme};

    #[cfg(feature = "bls12_381")]
    /// BLS12-381 Schemes
    pub mod bls12_381 {
        use crate::curve::bls12381::PairingCurve;
        pub use crate::curve::bls12381::{G1Curve, G2Curve};

        /// Public Keys on G1, Signatures on G2
        pub type G1Scheme = super::G1Scheme<PairingCurve>;
        /// Public Keys on G2, Signatures on G1
        pub type G2Scheme = super::G2Scheme<PairingCurve>;
    }

    #[cfg(feature = "bn254")]
    /// BLS12-381 Schemes
    pub mod bn254 {
        use crate::curve::bn254::PairingCurve;
        pub use crate::curve::bn254::{G1Curve, G2Curve};

        /// Public Keys on G1, Signatures on G2
        pub type G1Scheme = super::G1Scheme<PairingCurve>;
        /// Public Keys on G2, Signatures on G1
        pub type G2Scheme = super::G2Scheme<PairingCurve>;
    }
}

pub mod test_bls;