Skip to content

Commit 98bfada

Browse files
committed
Applying ChrisW comments.
1 parent 1b68fea commit 98bfada

File tree

2 files changed

+64
-69
lines changed

2 files changed

+64
-69
lines changed

secretsharing/ss.go

+51-57
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
package secretsharing
2222

2323
import (
24-
"errors"
2524
"fmt"
2625
"io"
2726

@@ -31,75 +30,65 @@ import (
3130

3231
// Share represents a share of a secret.
3332
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
3637
}
3738

3839
type 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.
8778
func (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 {
163153
func (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+
}

secretsharing/ss_test.go

+13-12
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ func TestSecretSharing(tt *testing.T) {
1414
t := uint(2)
1515
n := uint(5)
1616

17-
s, err := secretsharing.NewShamirSecretSharing(g, t, n)
18-
test.CheckNoErr(tt, err, "failed to create Shamir secret sharing")
17+
s := secretsharing.NewShamirSecretSharing(t)
1918

2019
want := g.RandomScalar(rand.Reader)
21-
shares := s.Shard(rand.Reader, want)
20+
shares, err := s.Shard(rand.Reader, want, n)
21+
test.CheckNoErr(tt, err, "failed to shard a secret")
2222
test.CheckOk(len(shares) == int(n), "bad num shares", tt)
2323

2424
tt.Run("subsetSize", func(ttt *testing.T) {
@@ -43,11 +43,11 @@ func TestVerifiableSecretSharing(tt *testing.T) {
4343
t := uint(3)
4444
n := uint(5)
4545

46-
vs, err := secretsharing.NewFeldmanSecretSharing(g, t, n)
47-
test.CheckNoErr(tt, err, "failed to create Feldman secret sharing")
46+
vs := secretsharing.NewFeldmanSecretSharing(t)
4847

4948
want := g.RandomScalar(rand.Reader)
50-
shares, com := vs.Shard(rand.Reader, want)
49+
shares, com, err := vs.Shard(rand.Reader, want, n)
50+
test.CheckNoErr(tt, err, "failed to shard a secret")
5151
test.CheckOk(len(shares) == int(n), "bad num shares", tt)
5252
test.CheckOk(len(com) == int(t+1), "bad num commitments", tt)
5353

@@ -76,6 +76,7 @@ func TestVerifiableSecretSharing(tt *testing.T) {
7676
tt.Run("badShares", func(ttt *testing.T) {
7777
badShares := make([]secretsharing.Share, len(shares))
7878
for i := range shares {
79+
badShares[i].ID = shares[i].ID.Copy()
7980
badShares[i].Value = shares[i].Value.Copy()
8081
badShares[i].Value.SetUint64(9)
8182
}
@@ -103,13 +104,13 @@ func BenchmarkSecretSharing(b *testing.B) {
103104
t := uint(3)
104105
n := uint(5)
105106

106-
s, _ := secretsharing.NewShamirSecretSharing(g, t, n)
107+
s := secretsharing.NewShamirSecretSharing(t)
107108
want := g.RandomScalar(rand.Reader)
108-
shares := s.Shard(rand.Reader, want)
109+
shares, _ := s.Shard(rand.Reader, want, n)
109110

110111
b.Run("Shard", func(b *testing.B) {
111112
for i := 0; i < b.N; i++ {
112-
s.Shard(rand.Reader, want)
113+
_, _ = s.Shard(rand.Reader, want, n)
113114
}
114115
})
115116

@@ -125,13 +126,13 @@ func BenchmarkVerifiableSecretSharing(b *testing.B) {
125126
t := uint(3)
126127
n := uint(5)
127128

128-
vs, _ := secretsharing.NewFeldmanSecretSharing(g, t, n)
129+
vs := secretsharing.NewFeldmanSecretSharing(t)
129130
want := g.RandomScalar(rand.Reader)
130-
shares, com := vs.Shard(rand.Reader, want)
131+
shares, com, _ := vs.Shard(rand.Reader, want, n)
131132

132133
b.Run("Shard", func(b *testing.B) {
133134
for i := 0; i < b.N; i++ {
134-
vs.Shard(rand.Reader, want)
135+
_, _, _ = vs.Shard(rand.Reader, want, n)
135136
}
136137
})
137138

0 commit comments

Comments
 (0)