Skip to content

Commit a4bfe72

Browse files
authored
Added a dlog proof to vss feldman to defend against the n-t+1 attack (#169)
1 parent 44537a7 commit a4bfe72

File tree

2 files changed

+62
-46
lines changed

2 files changed

+62
-46
lines changed

examples/verifiable_secret_sharing.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use curv::elliptic::curves::*;
2+
use sha2::Sha256;
23

34
/// secret_sharing_3_out_of_5
45
/// Feldman VSS, based on Paul Feldman. 1987. A practical scheme for non-interactive verifiable secret sharing.
@@ -16,7 +17,7 @@ pub fn secret_sharing_3_out_of_5<E: Curve>() {
1617

1718
let secret = Scalar::random();
1819

19-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share(3, 5, &secret);
20+
let (vss_scheme, secret_shares) = VerifiableSS::<E, Sha256>::share(3, 5, &secret);
2021

2122
let shares_vec = vec![
2223
secret_shares[0].clone(),
@@ -42,11 +43,11 @@ pub fn secret_sharing_3_out_of_5<E: Curve>() {
4243

4344
// test map (t,n) - (t',t')
4445
let s = &vec![0, 1, 2, 3, 4];
45-
let l0 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
46-
let l1 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
47-
let l2 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 2, s);
48-
let l3 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 3, s);
49-
let l4 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 4, s);
46+
let l0 = VerifiableSS::<E, Sha256>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
47+
let l1 = VerifiableSS::<E, Sha256>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
48+
let l2 = VerifiableSS::<E, Sha256>::map_share_to_new_params(&vss_scheme.parameters, 2, s);
49+
let l3 = VerifiableSS::<E, Sha256>::map_share_to_new_params(&vss_scheme.parameters, 3, s);
50+
let l4 = VerifiableSS::<E, Sha256>::map_share_to_new_params(&vss_scheme.parameters, 4, s);
5051

5152
let w = l0 * secret_shares[0].clone()
5253
+ l1 * secret_shares[1].clone()

src/cryptographic_primitives/secret_sharing/feldman_vss.rs

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::{fmt, ops};
1212

1313
use serde::{Deserialize, Serialize};
1414

15+
use crate::cryptographic_primitives::hashing::Digest;
16+
use crate::cryptographic_primitives::proofs::sigma_dlog::DLogProof;
1517
use crate::cryptographic_primitives::secret_sharing::Polynomial;
1618
use crate::elliptic::curves::{Curve, Point, Scalar};
1719
use crate::ErrorSS::{self, VerifyShareError};
@@ -27,11 +29,14 @@ pub struct ShamirSecretSharing {
2729
///
2830
/// implementation details: The code is using FE and GE. Each party is given an index from 1,..,n and a secret share of type FE.
2931
/// The index of the party is also the point on the polynomial where we treat this number as u32 but converting it to FE internally.
32+
///
33+
/// The scheme is augmented with a dlog proof for the constant commitment to protect against n-t+1 attack
3034
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
3135
#[serde(bound = "")]
32-
pub struct VerifiableSS<E: Curve> {
36+
pub struct VerifiableSS<E: Curve, H: Digest + Clone> {
3337
pub parameters: ShamirSecretSharing,
3438
pub commitments: Vec<Point<E>>,
39+
pub proof: DLogProof<E, H>,
3540
}
3641

3742
/// Shared secret produced by [VerifiableSS::share]
@@ -49,13 +54,13 @@ pub struct SecretShares<E: Curve> {
4954
polynomial: Polynomial<E>,
5055
}
5156

52-
impl<E: Curve> VerifiableSS<E> {
57+
impl<E: Curve, H: Digest + Clone> VerifiableSS<E, H> {
5358
pub fn reconstruct_limit(&self) -> u16 {
5459
self.parameters.threshold + 1
5560
}
5661

5762
// generate VerifiableSS from a secret
58-
pub fn share(t: u16, n: u16, secret: &Scalar<E>) -> (VerifiableSS<E>, SecretShares<E>) {
63+
pub fn share(t: u16, n: u16, secret: &Scalar<E>) -> (VerifiableSS<E, H>, SecretShares<E>) {
5964
assert!(t < n);
6065
let polynomial = Polynomial::<E>::sample_exact_with_fixed_const_term(t, secret.clone());
6166
let shares = polynomial.evaluate_many_bigint(1..=n).collect();
@@ -66,20 +71,23 @@ impl<E: Curve> VerifiableSS<E> {
6671
.iter()
6772
.map(|coef| g * coef)
6873
.collect::<Vec<_>>();
74+
75+
let proof = DLogProof::<E, H>::prove(&secret);
6976
(
7077
VerifiableSS {
7178
parameters: ShamirSecretSharing {
7279
threshold: t,
7380
share_count: n,
7481
},
7582
commitments,
83+
proof,
7684
},
7785
SecretShares { shares, polynomial },
7886
)
7987
}
8088

8189
// takes given VSS and generates a new VSS for the same secret and a secret shares vector to match the new commitments
82-
pub fn reshare(&self) -> (VerifiableSS<E>, Vec<Scalar<E>>) {
90+
pub fn reshare(&self) -> (VerifiableSS<E, H>, Vec<Scalar<E>>) {
8391
let t = self.parameters.threshold;
8492
let n = self.parameters.share_count;
8593

@@ -98,6 +106,7 @@ impl<E: Curve> VerifiableSS<E> {
98106
VerifiableSS {
99107
parameters: self.parameters.clone(),
100108
commitments: new_commitments,
109+
proof: self.proof.clone(),
101110
},
102111
secret_shares,
103112
)
@@ -110,7 +119,7 @@ impl<E: Curve> VerifiableSS<E> {
110119
n: u16,
111120
secret: &Scalar<E>,
112121
indicies: I,
113-
) -> (VerifiableSS<E>, SecretShares<E>)
122+
) -> (VerifiableSS<E, H>, SecretShares<E>)
114123
where
115124
I: IntoIterator<Item = NonZeroU16>,
116125
I::IntoIter: ExactSizeIterator,
@@ -129,13 +138,16 @@ impl<E: Curve> VerifiableSS<E> {
129138
.iter()
130139
.map(|coef| g * coef)
131140
.collect::<Vec<Point<E>>>();
141+
142+
let proof = DLogProof::<E, H>::prove(&secret);
132143
(
133144
VerifiableSS {
134145
parameters: ShamirSecretSharing {
135146
threshold: t,
136147
share_count: n,
137148
},
138149
commitments,
150+
proof,
139151
},
140152
SecretShares { shares, polynomial },
141153
)
@@ -172,7 +184,7 @@ impl<E: Curve> VerifiableSS<E> {
172184
.iter()
173185
.map(|i| Scalar::from(*i + 1))
174186
.collect::<Vec<_>>();
175-
VerifiableSS::<E>::lagrange_interpolation_at_zero(&points, shares)
187+
VerifiableSS::<E, H>::lagrange_interpolation_at_zero(&points, shares)
176188
}
177189

178190
// Performs a Lagrange interpolation in field Zp at the origin
@@ -224,6 +236,9 @@ impl<E: Curve> VerifiableSS<E> {
224236
}
225237

226238
pub fn validate_share(&self, secret_share: &Scalar<E>, index: u16) -> Result<(), ErrorSS> {
239+
if self.commitments[0] != self.proof.pk || !DLogProof::verify(&self.proof).is_ok() {
240+
return Err(VerifyShareError);
241+
}
227242
let g = Point::generator();
228243
let ss_point = g * secret_share;
229244
self.validate_share_public(&ss_point, index)
@@ -286,14 +301,14 @@ impl<E: Curve> ops::Deref for SecretShares<E> {
286301
#[cfg(test)]
287302
mod tests {
288303
use super::*;
289-
use crate::test_for_all_curves;
304+
use crate::test_for_all_curves_and_hashes;
290305

291-
test_for_all_curves!(test_secret_sharing_3_out_of_5_at_indices);
306+
test_for_all_curves_and_hashes!(test_secret_sharing_3_out_of_5_at_indices);
292307

293-
fn test_secret_sharing_3_out_of_5_at_indices<E: Curve>() {
308+
fn test_secret_sharing_3_out_of_5_at_indices<E: Curve, H: Digest + Clone>() {
294309
let secret = Scalar::random();
295310
let parties = [1, 2, 4, 5, 6];
296-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share_at_indices(
311+
let (vss_scheme, secret_shares) = VerifiableSS::<E, H>::share_at_indices(
297312
3,
298313
5,
299314
&secret,
@@ -313,12 +328,12 @@ mod tests {
313328
assert_eq!(secret, secret_reconstructed);
314329
}
315330

316-
test_for_all_curves!(test_secret_sharing_3_out_of_5);
331+
test_for_all_curves_and_hashes!(test_secret_sharing_3_out_of_5);
317332

318-
fn test_secret_sharing_3_out_of_5<E: Curve>() {
333+
fn test_secret_sharing_3_out_of_5<E: Curve, H: Digest + Clone>() {
319334
let secret = Scalar::random();
320335

321-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share(3, 5, &secret);
336+
let (vss_scheme, secret_shares) = VerifiableSS::<E, H>::share(3, 5, &secret);
322337

323338
let shares_vec = vec![
324339
secret_shares[0].clone(),
@@ -345,11 +360,11 @@ mod tests {
345360

346361
// test map (t,n) - (t',t')
347362
let s = &vec![0, 1, 2, 3, 4];
348-
let l0 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
349-
let l1 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
350-
let l2 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 2, s);
351-
let l3 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 3, s);
352-
let l4 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 4, s);
363+
let l0 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
364+
let l1 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
365+
let l2 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 2, s);
366+
let l3 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 3, s);
367+
let l4 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 4, s);
353368
let w = l0 * &secret_shares[0]
354369
+ l1 * &secret_shares[1]
355370
+ l2 * &secret_shares[2]
@@ -358,12 +373,12 @@ mod tests {
358373
assert_eq!(w, secret_reconstructed);
359374
}
360375

361-
test_for_all_curves!(test_secret_sharing_3_out_of_7);
376+
test_for_all_curves_and_hashes!(test_secret_sharing_3_out_of_7);
362377

363-
fn test_secret_sharing_3_out_of_7<E: Curve>() {
378+
fn test_secret_sharing_3_out_of_7<E: Curve, H: Digest + Clone>() {
364379
let secret = Scalar::random();
365380

366-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share(3, 7, &secret);
381+
let (vss_scheme, secret_shares) = VerifiableSS::<E, H>::share(3, 7, &secret);
367382

368383
let shares_vec = vec![
369384
secret_shares[0].clone(),
@@ -384,11 +399,11 @@ mod tests {
384399

385400
// test map (t,n) - (t',t')
386401
let s = &vec![0, 1, 3, 4, 6];
387-
let l0 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
388-
let l1 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
389-
let l3 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 3, s);
390-
let l4 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 4, s);
391-
let l6 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 6, s);
402+
let l0 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
403+
let l1 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
404+
let l3 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 3, s);
405+
let l4 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 4, s);
406+
let l6 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 6, s);
392407

393408
let w = l0 * &secret_shares[0]
394409
+ l1 * &secret_shares[1]
@@ -398,12 +413,12 @@ mod tests {
398413
assert_eq!(w, secret_reconstructed);
399414
}
400415

401-
test_for_all_curves!(test_secret_sharing_1_out_of_2);
416+
test_for_all_curves_and_hashes!(test_secret_sharing_1_out_of_2);
402417

403-
fn test_secret_sharing_1_out_of_2<E: Curve>() {
418+
fn test_secret_sharing_1_out_of_2<E: Curve, H: Digest + Clone>() {
404419
let secret = Scalar::random();
405420

406-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share(1, 2, &secret);
421+
let (vss_scheme, secret_shares) = VerifiableSS::<E, H>::share(1, 2, &secret);
407422

408423
let shares_vec = vec![secret_shares[0].clone(), secret_shares[1].clone()];
409424

@@ -419,23 +434,23 @@ mod tests {
419434

420435
// test map (t,n) - (t',t')
421436
let s = &vec![0, 1];
422-
let l0 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
423-
let l1 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
437+
let l0 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
438+
let l1 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 1, s);
424439
let w = l0 * &secret_shares[0] + l1 * &secret_shares[1];
425440
assert_eq!(w, secret_reconstructed);
426441
}
427442

428-
test_for_all_curves!(test_secret_sharing_1_out_of_3);
443+
test_for_all_curves_and_hashes!(test_secret_sharing_1_out_of_3);
429444

430-
fn test_secret_sharing_1_out_of_3<E: Curve>() {
445+
fn test_secret_sharing_1_out_of_3<E: Curve, H: Digest + Clone>() {
431446
let secret = Scalar::random();
432447

433-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share(1, 3, &secret);
448+
let (vss_scheme, secret_shares) = VerifiableSS::<E, H>::share(1, 3, &secret);
434449

435450
let shares_vec = vec![secret_shares[0].clone(), secret_shares[1].clone()];
436451

437452
// test commitment to point and sum of commitments
438-
let (vss_scheme2, secret_shares2) = VerifiableSS::<E>::share(1, 3, &secret);
453+
let (vss_scheme2, secret_shares2) = VerifiableSS::<E, H>::share(1, 3, &secret);
439454
let sum = &secret_shares[0] + &secret_shares2[0];
440455
let point_comm1 = vss_scheme.get_point_commitment(1);
441456
let point_comm2 = vss_scheme.get_point_commitment(2);
@@ -459,19 +474,19 @@ mod tests {
459474

460475
// test map (t,n) - (t',t')
461476
let s = &vec![0, 2];
462-
let l0 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
463-
let l2 = VerifiableSS::<E>::map_share_to_new_params(&vss_scheme.parameters, 2, s);
477+
let l0 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 0, s);
478+
let l2 = VerifiableSS::<E, H>::map_share_to_new_params(&vss_scheme.parameters, 2, s);
464479

465480
let w = l0 * &secret_shares[0] + l2 * &secret_shares[2];
466481
assert_eq!(w, secret_reconstructed);
467482
}
468483

469-
test_for_all_curves!(test_secret_resharing);
484+
test_for_all_curves_and_hashes!(test_secret_resharing);
470485

471-
fn test_secret_resharing<E: Curve>() {
486+
fn test_secret_resharing<E: Curve, H: Digest + Clone>() {
472487
let secret = Scalar::random();
473488

474-
let (vss_scheme, secret_shares) = VerifiableSS::<E>::share(1, 3, &secret);
489+
let (vss_scheme, secret_shares) = VerifiableSS::<E, H>::share(1, 3, &secret);
475490
let (new_vss_scheme, zero_secret_shares) = vss_scheme.reshare();
476491

477492
let new_share_party_1 = &secret_shares[0] + &zero_secret_shares[0];

0 commit comments

Comments
 (0)