2121package secretsharing
2222
2323import (
24- "errors"
2524 "fmt"
2625 "io"
2726
@@ -31,75 +30,65 @@ import (
3130
3231// Share represents a share of a secret.
3332type 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
3637}
3738
3839type SecretSharing struct {
39- g group.Group
40- t , n uint
40+ t uint // t is the threshold.
4141}
4242
4343// NewShamirSecretSharing implements a (t,n) Shamir's secret sharing.
4444// 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 } }
5647
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 {
5849 c := make ([]group.Scalar , s .t + 1 )
50+ g := secret .Group ()
51+ c [0 ] = secret .Copy ()
5952 for i := 1 ; i < len (c ); i ++ {
60- c [i ] = s . g .RandomScalar (rnd )
53+ c [i ] = g .RandomScalar (rnd )
6154 }
62- c [0 ] = secret .Copy ()
6355 return polynomial .New (c )
6456}
6557
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 )
6967 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 )}
7470 }
7571
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
8273}
8374
8475// Recover returns the secret provided more than t shares are given. Returns an
8576// error if the number of shares is not above the threshold or goes beyond the
8677// maximum number of shares.
8778func (s SecretSharing ) Recover (shares []Share ) (group.Scalar , error ) {
8879 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 ))
9281 }
9382
9483 x := make ([]group.Scalar , s .t + 1 )
9584 px := make ([]group.Scalar , s .t + 1 )
9685 for i := range shares [:s .t + 1 ] {
97- x [i ] = s . g . NewScalar (). SetUint64 ( shares [i ].ID )
86+ x [i ] = shares [i ].ID
9887 px [i ] = shares [i ].Value
9988 }
10089
10190 l := polynomial .NewLagrangePolynomial (x , px )
102- zero := s . g .NewScalar ()
91+ zero := shares [ 0 ]. ID . Group () .NewScalar ()
10392
10493 return l .Evaluate (zero ), nil
10594}
@@ -110,31 +99,33 @@ type VerifiableSecretSharing struct{ s SecretSharing }
11099
111100// NewFeldmanSecretSharing implements a (t,n) Feldman's verifiable secret
112101// 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 }
124106
125107// Shard splits the secret into n shares, and also returns a commitment to both
126108// the secret and the shares. The ShareCommitment must be sent to each party
127109// so each party can verify its share is correct. Sharding a secret more
128110// 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 ()
130117 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+ }
132123 shareComs := make (SharesCommitment , poly .Degree ()+ 1 )
133124 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 )))
135126 }
136127
137- return shares , shareComs
128+ return shares , shareComs , nil
138129}
139130
140131// 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 {
145136 return false
146137 }
147138
139+ g := s .ID .Group ()
148140 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 ])
151142 for i := lc - 1 ; i >= 0 ; i -- {
152- x .SetUint64 (s .ID )
153- sum .Mul (sum , x )
143+ sum .Mul (sum , s .ID )
154144 sum .Add (sum , c [i ])
155145 }
156- polI := v . s . g .NewElement ().MulGen (s .Value )
146+ polI := g .NewElement ().MulGen (s .Value )
157147 return polI .IsEqual (sum )
158148}
159149
@@ -163,3 +153,7 @@ func (v VerifiableSecretSharing) Verify(s Share, c SharesCommitment) bool {
163153func (v VerifiableSecretSharing ) Recover (shares []Share ) (group.Scalar , error ) {
164154 return v .s .Recover (shares )
165155}
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