vsss_rust/feldman_verifiability/mod.rs
1//! # Feldman's Verifiable Secret Sharing (VSS) Module
2//!
3//! This module implements Feldman's Verifiable Secret Sharing scheme, an extension
4//! of Shamir's Secret Sharing (SSS) that adds a layer of verifiability to the shared
5//! secrets. In Feldman's VSS, commitments to the coefficients of the polynomial used
6//! in Shamir's scheme are publicly shared. These commitments enable any party to verify
7//! their shares without revealing the secret or the coefficients of the polynomial.
8//!
9//! The key functionalities include:
10//! - Generation of shares based on a secret.
11//! - Creation of public commitments to the polynomial's coefficients.
12//! - Verification of shares against the public commitments.
13//! - Reconstruction of the secret from a subset of shares using Lagrange interpolation.
14//!
15//! This module requires `Polynomial`, `mod_exp`, `lagrange_interpolation_zero` and potentially other utility functions
16//! from the `utils` module for its operations.
17
18
19use crate::utils::{Polynomial, mod_exp,lagrange_interpolation_zero};
20use num_bigint::{BigUint, ToBigUint};
21use num_traits::One;
22
23/// Represents the public parameters for the Feldman VSS scheme.
24pub struct FeldmanVSSParams {
25 pub g: BigUint, // Generator of the group G
26 pub q: BigUint, // Prime order of the group G
27}
28
29impl FeldmanVSSParams {
30
31 /// Initializes Feldman VSS parameters with a generator and prime order.
32 pub fn new(g: BigUint, q: BigUint) -> Self {
33 FeldmanVSSParams { g, q }
34 }
35
36
37 /// Generates shares for Shamir's Secret Sharing (SSS) scheme and creates commitments for
38 /// Feldman's Verifiable Secret Sharing (VSS) based on a provided secret, a threshold,
39 /// and the total number of shares. It combines the secret sharing mechanism with a
40 /// verifiable component by publishing commitments to the coefficients of the polynomial
41 /// used to generate the shares.
42 ///
43 /// # Arguments
44 ///
45 /// * `secret` - A `BigUint` representing the secret to be shared.
46 /// * `threshold` - The minimum number of shares required to reconstruct the secret.
47 /// * `num_shares` - The total number of shares to be generated.
48 ///
49 /// # Returns
50 ///
51 /// A tuple containing two vectors:
52 /// - The first vector contains tuples of `BigUint`, each representing a share with an
53 /// index (x-value) and the corresponding share value (y-value).
54 /// - The second vector contains `BigUint` commitments to the coefficients of the polynomial,
55 /// enabling the verification of shares without revealing the coefficients themselves.
56
57 pub fn generate_shares(&self, secret: &BigUint, threshold: usize, num_shares: usize) -> (Vec<(BigUint, BigUint)>, Vec<BigUint>) {
58 let poly = Polynomial::new_for_shamir(threshold - 1, secret.bits() as usize, secret);
59 let mut shares = Vec::with_capacity(num_shares);
60
61 // Generate shares using the polynomial, similar to Shamir's scheme
62 for i in 1..=num_shares {
63 let x = i.to_biguint().unwrap();
64 let y = poly.evaluate(&x) % &self.q; // Ensure the evaluation is done modulo q
65 shares.push((x, y));
66 }
67
68 // Generate commitments for the polynomial's coefficients for verifiability
69 let commitments = self.generate_commitments(&poly);
70
71 (shares, commitments)
72 }
73
74 /// Generates verifiable commitments to the coefficients of the polynomial used in the secret sharing.
75 ///
76 /// In Feldman's Verifiable Secret Sharing scheme, these commitments are made public and allow any party
77 /// to verify their shares without compromising the security of the secret or needing access to the polynomial's
78 /// coefficients directly. Each commitment is calculated using the group's generator `g` raised to the power
79 /// of the coefficient, all operations performed modulo `q`, the prime order of the group.
80 ///
81 /// # Arguments
82 ///
83 /// * `polynomial` - A reference to the `Polynomial` instance that represents the polynomial used
84 /// to generate shares in the secret sharing scheme. The polynomial's coefficients are used to
85 /// create the commitments.
86 ///
87 /// # Returns
88 ///
89 /// A vector of `BigUint` representing the commitments to each coefficient of the polynomial.
90 /// These commitments can be publicly shared to enable verification of shares by participants
91 /// without revealing the polynomial's coefficients or the shared secret itself.
92 ///
93 /// Each commitment is of the form `g^coef mod q`, where `g` is the generator of the group,
94 /// `coef` is a coefficient of the polynomial, and `q` is the prime order of the group.
95 fn generate_commitments(&self, polynomial: &Polynomial) -> Vec<BigUint> {
96 polynomial.coefficients.iter().map(|coef| {
97 mod_exp(&self.g, coef, &self.q) // Compute g^coef mod q for each coefficient
98 }).collect()
99 }
100
101}
102
103
104/// Verifies a share against the public commitments using the Feldman Verifiable Secret Sharing scheme.
105/// This function checks if a share is valid by verifying that g^share equals the product of the commitments
106/// raised to the power of their respective indices, all operations performed modulo q.
107///
108/// # Arguments
109///
110/// * `i` - A `BigUint` representing the index of the share being verified.
111/// * `share` - A `BigUint` representing the share value associated with the index `i`.
112/// * `commitments` - A slice of `BigUint` representing the public commitments to the polynomial coefficients.
113/// * `params` - A reference to the `FeldmanVSSParams` containing the public parameters (g and q) of the scheme.
114///
115/// # Returns
116///
117/// `true` if the share is valid according to the verification equation, otherwise `false`.
118
119pub fn verify_share(
120 i: &BigUint, // Share index
121 share: &BigUint, // Share value
122 commitments: &[BigUint], // Public commitments
123 params: &FeldmanVSSParams, // VSS parameters
124) -> bool {
125 // Calculate the left-hand side (LHS) as g^share mod q
126 let lhs = mod_exp(¶ms.g, share, ¶ms.q);
127
128 // Calculate the right-hand side (RHS) as the product of commitments raised to the power of the share index
129 let rhs = commitments.iter().enumerate().fold(BigUint::one(), |acc, (j, commitment)| {
130 let exponent = i.modpow(&BigUint::from(j), ¶ms.q);
131 (acc * mod_exp(commitment, &exponent, ¶ms.q)) % ¶ms.q
132 });
133
134 lhs == rhs
135}
136
137/// Reconstructs the secret from a set of shares using Lagrange interpolation at zero.
138/// This function is a critical part of Shamir's Secret Sharing, enabling the recovery
139/// of the secret from a minimum number of shares without revealing the shares themselves.
140///
141/// # Arguments
142///
143/// * `shares` - A slice of tuples containing shares, where each tuple consists of an
144/// index (x-value) and the corresponding share value (y-value).
145/// * `modulus` - A `BigUint` representing the modulus used for the finite field operations,
146/// which should be the same as used in share generation.
147///
148/// # Returns
149///
150/// An `Option<BigUint>` containing the reconstructed secret if successful, otherwise `None`.
151
152pub fn reconstruct_secret(shares: &[(BigUint, BigUint)], modulus: &BigUint) -> Option<BigUint> {
153 lagrange_interpolation_zero(shares, modulus)
154}
155
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160 use num_bigint::ToBigUint;
161 use crate::utils::generate_prime;
162
163 #[test]
164 fn test_share_generation_and_verification() {
165 let secret = 1234.to_biguint().unwrap();
166 let threshold = 3;
167 let num_shares = 5;
168
169 let g = 2.to_biguint().unwrap();
170 let q = generate_prime(256);
171
172 let params = FeldmanVSSParams::new(g, q);
173
174 let (shares, commitments) = params.generate_shares(&secret, threshold, num_shares);
175
176 for (i, &(ref x, ref y)) in shares.iter().enumerate() {
177 assert!(verify_share(x, y, &commitments, ¶ms), "Share {} failed verification", i + 1);
178 }
179
180 let reconstructed_secret = reconstruct_secret(&shares[..threshold], ¶ms.q).unwrap();
181 assert_eq!(secret, reconstructed_secret, "Reconstructed secret does not match the original secret.");
182 }
183}