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
/*
    Copyright Michael Lodder. All Rights Reserved.
    SPDX-License-Identifier: Apache-2.0
*/
//! Feldman's Verifiable secret sharing scheme.
//! (see <https://www.cs.umd.edu/~gasarch/TOPICS/secretsharing/feldmanVSS.pdf>.
use crate::*;
use elliptic_curve::{ff::Field, group::Group};
use rand_core::{CryptoRng, RngCore};

/// A secret sharing scheme that uses feldman commitments as verifiers
/// (see https://www.cs.umd.edu/~gasarch/TOPICS/secretsharing/feldmanVSS.pdf)
pub trait Feldman<G, I, S>: Shamir<G::Scalar, I, S>
where
    G: Group,
    I: ShareIdentifier,
    S: Share<Identifier = I>,
{
    /// The verifier set
    type VerifierSet: FeldmanVerifierSet<G>;

    /// Create shares from a secret.
    /// `F` is the prime field
    /// `generator` is the generator point to use for computing feldman verifiers.
    /// If [`None`], the default generator is used.
    fn split_secret_with_verifier(
        threshold: usize,
        limit: usize,
        secret: G::Scalar,
        generator: Option<G>,
        rng: impl RngCore + CryptoRng,
    ) -> VsssResult<(Self::ShareSet, Self::VerifierSet)> {
        check_params(threshold, limit)?;
        let g = generator.unwrap_or_else(G::generator);
        if g.is_identity().into() {
            return Err(Error::InvalidGenerator);
        }
        let mut polynomial = Self::InnerPolynomial::create(threshold);
        polynomial.fill(secret, rng, threshold)?;
        let mut verifier_set = Self::VerifierSet::empty_feldman_set_with_capacity(threshold, g);
        // Generate the verifiable commitments to the polynomial for the shares
        // Each share is multiple of the polynomial and the specified generator point.
        // {g^p0, g^p1, g^p2, ..., g^pn}
        let coefficients = polynomial.coefficients();
        verifier_set
            .verifiers_mut()
            .iter_mut()
            .take(threshold)
            .enumerate()
            .for_each(|(i, vs)| {
                *vs = g * coefficients[i];
            });
        let shares = create_shares(&polynomial, threshold, limit)?;
        polynomial
            .coefficients_mut()
            .iter_mut()
            .take(threshold)
            .for_each(|c| *c = G::Scalar::ZERO);
        Ok((shares, verifier_set))
    }
}

#[cfg(any(feature = "alloc", feature = "std"))]
/// Create shares from a secret.
/// `generator` is the point to use for computing feldman verifiers.
/// If None, the default generator is used.
pub fn split_secret<G: Group + Default, I: ShareIdentifier, S: Share<Identifier = I>>(
    threshold: usize,
    limit: usize,
    secret: G::Scalar,
    generator: Option<G>,
    rng: impl RngCore + CryptoRng,
) -> VsssResult<(Vec<S>, Vec<G>)> {
    StdVsss::split_secret_with_verifier(threshold, limit, secret, generator, rng)
}