@@ -12,6 +12,8 @@ use std::{fmt, ops};
12
12
13
13
use serde:: { Deserialize , Serialize } ;
14
14
15
+ use crate :: cryptographic_primitives:: hashing:: Digest ;
16
+ use crate :: cryptographic_primitives:: proofs:: sigma_dlog:: DLogProof ;
15
17
use crate :: cryptographic_primitives:: secret_sharing:: Polynomial ;
16
18
use crate :: elliptic:: curves:: { Curve , Point , Scalar } ;
17
19
use crate :: ErrorSS :: { self , VerifyShareError } ;
@@ -27,11 +29,14 @@ pub struct ShamirSecretSharing {
27
29
///
28
30
/// 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.
29
31
/// 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
30
34
#[ derive( Clone , PartialEq , Debug , Serialize , Deserialize ) ]
31
35
#[ serde( bound = "" ) ]
32
- pub struct VerifiableSS < E : Curve > {
36
+ pub struct VerifiableSS < E : Curve , H : Digest + Clone > {
33
37
pub parameters : ShamirSecretSharing ,
34
38
pub commitments : Vec < Point < E > > ,
39
+ pub proof : DLogProof < E , H > ,
35
40
}
36
41
37
42
/// Shared secret produced by [VerifiableSS::share]
@@ -49,13 +54,13 @@ pub struct SecretShares<E: Curve> {
49
54
polynomial : Polynomial < E > ,
50
55
}
51
56
52
- impl < E : Curve > VerifiableSS < E > {
57
+ impl < E : Curve , H : Digest + Clone > VerifiableSS < E , H > {
53
58
pub fn reconstruct_limit ( & self ) -> u16 {
54
59
self . parameters . threshold + 1
55
60
}
56
61
57
62
// 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 > ) {
59
64
assert ! ( t < n) ;
60
65
let polynomial = Polynomial :: < E > :: sample_exact_with_fixed_const_term ( t, secret. clone ( ) ) ;
61
66
let shares = polynomial. evaluate_many_bigint ( 1 ..=n) . collect ( ) ;
@@ -66,20 +71,23 @@ impl<E: Curve> VerifiableSS<E> {
66
71
. iter ( )
67
72
. map ( |coef| g * coef)
68
73
. collect :: < Vec < _ > > ( ) ;
74
+
75
+ let proof = DLogProof :: < E , H > :: prove ( & secret) ;
69
76
(
70
77
VerifiableSS {
71
78
parameters : ShamirSecretSharing {
72
79
threshold : t,
73
80
share_count : n,
74
81
} ,
75
82
commitments,
83
+ proof,
76
84
} ,
77
85
SecretShares { shares, polynomial } ,
78
86
)
79
87
}
80
88
81
89
// 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 > > ) {
83
91
let t = self . parameters . threshold ;
84
92
let n = self . parameters . share_count ;
85
93
@@ -98,6 +106,7 @@ impl<E: Curve> VerifiableSS<E> {
98
106
VerifiableSS {
99
107
parameters : self . parameters . clone ( ) ,
100
108
commitments : new_commitments,
109
+ proof : self . proof . clone ( ) ,
101
110
} ,
102
111
secret_shares,
103
112
)
@@ -110,7 +119,7 @@ impl<E: Curve> VerifiableSS<E> {
110
119
n : u16 ,
111
120
secret : & Scalar < E > ,
112
121
indicies : I ,
113
- ) -> ( VerifiableSS < E > , SecretShares < E > )
122
+ ) -> ( VerifiableSS < E , H > , SecretShares < E > )
114
123
where
115
124
I : IntoIterator < Item = NonZeroU16 > ,
116
125
I :: IntoIter : ExactSizeIterator ,
@@ -129,13 +138,16 @@ impl<E: Curve> VerifiableSS<E> {
129
138
. iter ( )
130
139
. map ( |coef| g * coef)
131
140
. collect :: < Vec < Point < E > > > ( ) ;
141
+
142
+ let proof = DLogProof :: < E , H > :: prove ( & secret) ;
132
143
(
133
144
VerifiableSS {
134
145
parameters : ShamirSecretSharing {
135
146
threshold : t,
136
147
share_count : n,
137
148
} ,
138
149
commitments,
150
+ proof,
139
151
} ,
140
152
SecretShares { shares, polynomial } ,
141
153
)
@@ -172,7 +184,7 @@ impl<E: Curve> VerifiableSS<E> {
172
184
. iter ( )
173
185
. map ( |i| Scalar :: from ( * i + 1 ) )
174
186
. collect :: < Vec < _ > > ( ) ;
175
- VerifiableSS :: < E > :: lagrange_interpolation_at_zero ( & points, shares)
187
+ VerifiableSS :: < E , H > :: lagrange_interpolation_at_zero ( & points, shares)
176
188
}
177
189
178
190
// Performs a Lagrange interpolation in field Zp at the origin
@@ -224,6 +236,9 @@ impl<E: Curve> VerifiableSS<E> {
224
236
}
225
237
226
238
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
+ }
227
242
let g = Point :: generator ( ) ;
228
243
let ss_point = g * secret_share;
229
244
self . validate_share_public ( & ss_point, index)
@@ -286,14 +301,14 @@ impl<E: Curve> ops::Deref for SecretShares<E> {
286
301
#[ cfg( test) ]
287
302
mod tests {
288
303
use super :: * ;
289
- use crate :: test_for_all_curves ;
304
+ use crate :: test_for_all_curves_and_hashes ;
290
305
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) ;
292
307
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 > ( ) {
294
309
let secret = Scalar :: random ( ) ;
295
310
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 (
297
312
3 ,
298
313
5 ,
299
314
& secret,
@@ -313,12 +328,12 @@ mod tests {
313
328
assert_eq ! ( secret, secret_reconstructed) ;
314
329
}
315
330
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) ;
317
332
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 > ( ) {
319
334
let secret = Scalar :: random ( ) ;
320
335
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) ;
322
337
323
338
let shares_vec = vec ! [
324
339
secret_shares[ 0 ] . clone( ) ,
@@ -345,11 +360,11 @@ mod tests {
345
360
346
361
// test map (t,n) - (t',t')
347
362
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) ;
353
368
let w = l0 * & secret_shares[ 0 ]
354
369
+ l1 * & secret_shares[ 1 ]
355
370
+ l2 * & secret_shares[ 2 ]
@@ -358,12 +373,12 @@ mod tests {
358
373
assert_eq ! ( w, secret_reconstructed) ;
359
374
}
360
375
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) ;
362
377
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 > ( ) {
364
379
let secret = Scalar :: random ( ) ;
365
380
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) ;
367
382
368
383
let shares_vec = vec ! [
369
384
secret_shares[ 0 ] . clone( ) ,
@@ -384,11 +399,11 @@ mod tests {
384
399
385
400
// test map (t,n) - (t',t')
386
401
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) ;
392
407
393
408
let w = l0 * & secret_shares[ 0 ]
394
409
+ l1 * & secret_shares[ 1 ]
@@ -398,12 +413,12 @@ mod tests {
398
413
assert_eq ! ( w, secret_reconstructed) ;
399
414
}
400
415
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) ;
402
417
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 > ( ) {
404
419
let secret = Scalar :: random ( ) ;
405
420
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) ;
407
422
408
423
let shares_vec = vec ! [ secret_shares[ 0 ] . clone( ) , secret_shares[ 1 ] . clone( ) ] ;
409
424
@@ -419,23 +434,23 @@ mod tests {
419
434
420
435
// test map (t,n) - (t',t')
421
436
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) ;
424
439
let w = l0 * & secret_shares[ 0 ] + l1 * & secret_shares[ 1 ] ;
425
440
assert_eq ! ( w, secret_reconstructed) ;
426
441
}
427
442
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) ;
429
444
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 > ( ) {
431
446
let secret = Scalar :: random ( ) ;
432
447
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) ;
434
449
435
450
let shares_vec = vec ! [ secret_shares[ 0 ] . clone( ) , secret_shares[ 1 ] . clone( ) ] ;
436
451
437
452
// 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) ;
439
454
let sum = & secret_shares[ 0 ] + & secret_shares2[ 0 ] ;
440
455
let point_comm1 = vss_scheme. get_point_commitment ( 1 ) ;
441
456
let point_comm2 = vss_scheme. get_point_commitment ( 2 ) ;
@@ -459,19 +474,19 @@ mod tests {
459
474
460
475
// test map (t,n) - (t',t')
461
476
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) ;
464
479
465
480
let w = l0 * & secret_shares[ 0 ] + l2 * & secret_shares[ 2 ] ;
466
481
assert_eq ! ( w, secret_reconstructed) ;
467
482
}
468
483
469
- test_for_all_curves ! ( test_secret_resharing) ;
484
+ test_for_all_curves_and_hashes ! ( test_secret_resharing) ;
470
485
471
- fn test_secret_resharing < E : Curve > ( ) {
486
+ fn test_secret_resharing < E : Curve , H : Digest + Clone > ( ) {
472
487
let secret = Scalar :: random ( ) ;
473
488
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) ;
475
490
let ( new_vss_scheme, zero_secret_shares) = vss_scheme. reshare ( ) ;
476
491
477
492
let new_share_party_1 = & secret_shares[ 0 ] + & zero_secret_shares[ 0 ] ;
0 commit comments