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