This crate provides various cryptography secret sharing schemes.
This is intended to be a mid-level API by providing the secret sharing schemes without any specific
finite field or big number library. The only requirement, is to implement the traits Group
and Field
from this library.
The implementer must have a basic understanding of finite fields. The examples folder shows
how this can be done for various elliptic curves.
The first scheme is by Adi Shamir in '79 - Shamir Secret Sharing.
The second scheme is by Paul Feldman in '87 - Feldman Verifiable Secret Sharing.
The third scheme is by Torben Pedersen in '91 - Pedersen Verifiable Secret Sharing.
Each of these can be used in sub protocols like threshold signatures or distributed key generation
Once these traits are implemented for the secret field, the secret can be split into shares using shamir::Scheme
.
To use Feldman or Pedersen with elliptic curves, Group
will need to be implemented for the group elements as well as the field elements.
Each scheme requires specifying the threshold and the maximum number of shares to create.
let scheme = Scheme::new(threshold, limit);
To split a secret, we also need a cryptographically secure pseudorandom number generator (CSPRNG). Secrets should be valid members of the field to prevent malleability i.e. multiple values could represent the same secret.
Shamir
let shares = scheme.split_secret(&mut rng, &secret)?;
Feldman's Verifiable Secret Sharing returns cryptographic commitments to the polynomial allowing the shares to be verified before
combining shares. The default generator to use for the commitments is the value returned by the field parameter R::random()
.
Feldman
let (verifier, shares) = scheme.split_secret(&mut rng, &secret, None)?;
for share in &shares {
scheme.verify_share(&share, &verifier)?;
}
Verify share returns void on success but an error on failure. Verification is performed by computing the sum of products c_0 * c_1^i * c_2^{i^2} ... c_t^{i^t} and comparing against specified share.
Pedersen's Verifiable Secret Sharing adds an additional blinding factor when splitting and thus requires an additional generator. If no generator is specified for the blinding factor, a random one is used.
Pedersen
let result = scheme.split_secret(&mut rng, &secret, None, None)?;
let secret_shares = result.secret_shares;
let blinding_shares = result.blinding_shares;
for i in 0..secret_shares.len() {
scheme.verify_share(secret_shares[i], blinding_shares[i], &result.verifier)?;
}
Each scheme has the same API for combining shares to reconstruct the original secret. Obviously, at least the threshold number of shares are required to combine successfully. Otherwise it returns an error.
let secret = scheme.combine_shares(shares.as_slice())?;