1
- // Package secretsharing provides methods to split secrets in shares.
1
+ // Package secretsharing provides methods to split secrets into shares.
2
2
//
3
3
// Let n be the number of parties, and t the number of corrupted parties such
4
4
// that 0 <= t < n. A (t,n) secret sharing allows to split a secret into n
8
8
// which relies on Lagrange polynomial interpolation.
9
9
//
10
10
// The NewFeldmanSecretSharing function creates a Feldman secret sharing [2],
11
- // which extends Shamir's by allowing to verify that a share was honestly
12
- // generated.
11
+ // which extends Shamir's by allowing to verify that a share is part of a
12
+ // committed secret.
13
+ //
14
+ // In this implementation, secret sharing is defined over the scalar field of
15
+ // a prime order group.
13
16
//
14
17
// References
15
18
//
@@ -28,11 +31,11 @@ import (
28
31
29
32
// Share represents a share of a secret.
30
33
type Share struct {
31
- ID uint // ID uniquely identifies a share in a secret sharing instance.
34
+ ID uint64 // ID uniquely identifies a share in a secret sharing instance.
32
35
Value group.Scalar // Value stores the share generated from a secret sharing instance.
33
36
}
34
37
35
- type ss struct {
38
+ type SecretSharing struct {
36
39
g group.Group
37
40
t , n uint
38
41
}
@@ -41,47 +44,47 @@ type ss struct {
41
44
// A (t,n) secret sharing allows to split a secret into n shares, such that the
42
45
// secret can be only recovered from any subset of t+1 shares. Returns an error
43
46
// if 0 <= t < n does not hold.
44
- func NewShamirSecretSharing (g group.Group , t , n uint ) (ss , error ) {
47
+ func NewShamirSecretSharing (g group.Group , t , n uint ) (SecretSharing , error ) {
45
48
if t >= n {
46
- return ss {}, errors .New ("secretsharing: bad parameters" )
49
+ return SecretSharing {}, errors .New ("secretsharing: bad parameters" )
47
50
}
48
- return ss {g : g , t : t , n : n }, nil
51
+ return SecretSharing {g : g , t : t , n : n }, nil
49
52
}
50
53
51
54
// Params returns the t and n parameters of the secret sharing.
52
- func (s ss ) Params () (t , n uint ) { return s .t , s .n }
55
+ func (s SecretSharing ) Params () (t , n uint ) { return s .t , s .n }
53
56
54
- func (s ss ) polyFromSecret (rnd io.Reader , secret group.Scalar ) (p polynomial.Polynomial ) {
57
+ func (s SecretSharing ) polyFromSecret (rnd io.Reader , secret group.Scalar ) (p polynomial.Polynomial ) {
55
58
c := make ([]group.Scalar , s .t + 1 )
56
- for i := range c {
59
+ for i := 1 ; i < len ( c ); i ++ {
57
60
c [i ] = s .g .RandomScalar (rnd )
58
61
}
59
- c [0 ]. Set ( secret )
62
+ c [0 ] = secret . Copy ( )
60
63
return polynomial .New (c )
61
64
}
62
65
63
- func (s ss ) generateShares (poly polynomial.Polynomial ) []Share {
66
+ func (s SecretSharing ) generateShares (poly polynomial.Polynomial ) []Share {
64
67
shares := make ([]Share , s .n )
65
68
x := s .g .NewScalar ()
66
69
for i := range shares {
67
70
id := i + 1
68
71
x .SetUint64 (uint64 (id ))
69
- shares [i ].ID = uint (id )
72
+ shares [i ].ID = uint64 (id )
70
73
shares [i ].Value = poly .Evaluate (x )
71
74
}
72
75
73
76
return shares
74
77
}
75
78
76
79
// Shard splits the secret into n shares.
77
- func (s ss ) Shard (rnd io.Reader , secret group.Scalar ) []Share {
80
+ func (s SecretSharing ) Shard (rnd io.Reader , secret group.Scalar ) []Share {
78
81
return s .generateShares (s .polyFromSecret (rnd , secret ))
79
82
}
80
83
81
84
// Recover returns the secret provided more than t shares are given. Returns an
82
85
// error if the number of shares is not above the threshold or goes beyond the
83
86
// maximum number of shares.
84
- func (s ss ) Recover (shares []Share ) (group.Scalar , error ) {
87
+ func (s SecretSharing ) Recover (shares []Share ) (group.Scalar , error ) {
85
88
if l := len (shares ); l <= int (s .t ) {
86
89
return nil , fmt .Errorf ("secretsharing: does not reach the threshold %v with %v shares" , s .t , l )
87
90
} else if l > int (s .n ) {
@@ -91,7 +94,7 @@ func (s ss) Recover(shares []Share) (group.Scalar, error) {
91
94
x := make ([]group.Scalar , s .t + 1 )
92
95
px := make ([]group.Scalar , s .t + 1 )
93
96
for i := range shares [:s .t + 1 ] {
94
- x [i ] = s .g .NewScalar ().SetUint64 (uint64 ( shares [i ].ID ) )
97
+ x [i ] = s .g .NewScalar ().SetUint64 (shares [i ].ID )
95
98
px [i ] = shares [i ].Value
96
99
}
97
100
@@ -103,31 +106,32 @@ func (s ss) Recover(shares []Share) (group.Scalar, error) {
103
106
104
107
type SharesCommitment = []group.Element
105
108
106
- type vss struct { s ss }
109
+ type VerifiableSecretSharing struct { s SecretSharing }
107
110
108
111
// NewFeldmanSecretSharing implements a (t,n) Feldman's verifiable secret
109
112
// sharing. A (t,n) secret sharing allows to split a secret into n shares, such
110
113
// that the secret can be only recovered from any subset of t+1 shares. This
111
114
// method is verifiable because once the shares and the secret are committed
112
115
// during sharding, one can later verify whether the share was generated
113
116
// honestly. Returns an error if 0 < t <= n does not hold.
114
- func NewFeldmanSecretSharing (g group.Group , t , n uint ) (vss , error ) {
117
+ func NewFeldmanSecretSharing (g group.Group , t , n uint ) (VerifiableSecretSharing , error ) {
115
118
s , err := NewShamirSecretSharing (g , t , n )
116
- return vss {s }, err
119
+ return VerifiableSecretSharing {s }, err
117
120
}
118
121
119
122
// Params returns the t and n parameters of the secret sharing.
120
- func (v vss ) Params () (t , n uint ) { return v .s .Params () }
123
+ func (v VerifiableSecretSharing ) Params () (t , n uint ) { return v .s .Params () }
121
124
122
125
// Shard splits the secret into n shares, and also returns a commitment to both
123
- // the secret and the shares.
124
- func (v vss ) Shard (rnd io.Reader , secret group.Scalar ) ([]Share , SharesCommitment ) {
126
+ // the secret and the shares. The ShareCommitment must be sent to each party
127
+ // so each party can verify its share is correct. Sharding a secret more
128
+ // than once produces ShareCommitments with the same first entry.
129
+ func (v VerifiableSecretSharing ) Shard (rnd io.Reader , secret group.Scalar ) ([]Share , SharesCommitment ) {
125
130
poly := v .s .polyFromSecret (rnd , secret )
126
131
shares := v .s .generateShares (poly )
127
- coeffs := poly .Coefficients ()
128
- shareComs := make (SharesCommitment , len (coeffs ))
129
- for i := range coeffs {
130
- shareComs [i ] = v .s .g .NewElement ().MulGen (coeffs [i ])
132
+ shareComs := make (SharesCommitment , poly .Degree ()+ 1 )
133
+ for i := range shareComs {
134
+ shareComs [i ] = v .s .g .NewElement ().MulGen (poly .Coefficient (uint (i )))
131
135
}
132
136
133
137
return shares , shareComs
@@ -136,7 +140,7 @@ func (v vss) Shard(rnd io.Reader, secret group.Scalar) ([]Share, SharesCommitmen
136
140
// Verify returns true if a share was produced by sharding a secret. It uses
137
141
// the share commitments generated by the Shard function to verify this
138
142
// property.
139
- func (v vss ) Verify (s Share , c SharesCommitment ) bool {
143
+ func (v VerifiableSecretSharing ) Verify (s Share , c SharesCommitment ) bool {
140
144
if len (c ) != int (v .s .t + 1 ) {
141
145
return false
142
146
}
@@ -145,7 +149,7 @@ func (v vss) Verify(s Share, c SharesCommitment) bool {
145
149
sum := v .s .g .NewElement ().Set (c [lc ])
146
150
x := v .s .g .NewScalar ()
147
151
for i := lc - 1 ; i >= 0 ; i -- {
148
- x .SetUint64 (uint64 ( s .ID ) )
152
+ x .SetUint64 (s .ID )
149
153
sum .Mul (sum , x )
150
154
sum .Add (sum , c [i ])
151
155
}
@@ -156,4 +160,6 @@ func (v vss) Verify(s Share, c SharesCommitment) bool {
156
160
// Recover returns the secret provided more than t shares are given. Returns an
157
161
// error if the number of shares is not above the threshold (t) or is larger
158
162
// than the maximum number of shares (n).
159
- func (v vss ) Recover (shares []Share ) (group.Scalar , error ) { return v .s .Recover (shares ) }
163
+ func (v VerifiableSecretSharing ) Recover (shares []Share ) (group.Scalar , error ) {
164
+ return v .s .Recover (shares )
165
+ }
0 commit comments