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;