Skip to content

Commit da1ac24

Browse files
committed
Updates after cjpatton's review.
1 parent 28db5bf commit da1ac24

File tree

2 files changed

+42
-37
lines changed

2 files changed

+42
-37
lines changed

math/polynomial/polynomial.go

+6-7
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ func (p Polynomial) Evaluate(x group.Scalar) group.Scalar {
5656
return px
5757
}
5858

59-
// Coefficients returns a deep-copy of the polynomial's coefficients in
60-
// ascending order with respect to the degree.
61-
func (p Polynomial) Coefficients() []group.Scalar {
62-
c := make([]group.Scalar, len(p.c))
63-
for i := range p.c {
64-
c[i] = p.c[i].Copy()
59+
// Coefficient returns a deep-copy of the n-th polynomial's coefficient.
60+
// Note coefficients are sorted in ascending order with respect to the degree.
61+
func (p Polynomial) Coefficient(n uint) group.Scalar {
62+
if int(n) >= len(p.c) {
63+
panic("polynomial: invalid index for coefficient")
6564
}
66-
return c
65+
return p.c[n].Copy()
6766
}
6867

6968
// LagrangePolynomial stores a Lagrange polynomial over the set of scalars of a group.

secretsharing/ss.go

+36-30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Package secretsharing provides methods to split secrets in shares.
1+
// Package secretsharing provides methods to split secrets into shares.
22
//
33
// Let n be the number of parties, and t the number of corrupted parties such
44
// that 0 <= t < n. A (t,n) secret sharing allows to split a secret into n
@@ -8,8 +8,11 @@
88
// which relies on Lagrange polynomial interpolation.
99
//
1010
// 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.
1316
//
1417
// References
1518
//
@@ -28,11 +31,11 @@ import (
2831

2932
// Share represents a share of a secret.
3033
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.
3235
Value group.Scalar // Value stores the share generated from a secret sharing instance.
3336
}
3437

35-
type ss struct {
38+
type SecretSharing struct {
3639
g group.Group
3740
t, n uint
3841
}
@@ -41,47 +44,47 @@ type ss struct {
4144
// A (t,n) secret sharing allows to split a secret into n shares, such that the
4245
// secret can be only recovered from any subset of t+1 shares. Returns an error
4346
// 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) {
4548
if t >= n {
46-
return ss{}, errors.New("secretsharing: bad parameters")
49+
return SecretSharing{}, errors.New("secretsharing: bad parameters")
4750
}
48-
return ss{g: g, t: t, n: n}, nil
51+
return SecretSharing{g: g, t: t, n: n}, nil
4952
}
5053

5154
// 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 }
5356

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) {
5558
c := make([]group.Scalar, s.t+1)
56-
for i := range c {
59+
for i := 1; i < len(c); i++ {
5760
c[i] = s.g.RandomScalar(rnd)
5861
}
59-
c[0].Set(secret)
62+
c[0] = secret.Copy()
6063
return polynomial.New(c)
6164
}
6265

63-
func (s ss) generateShares(poly polynomial.Polynomial) []Share {
66+
func (s SecretSharing) generateShares(poly polynomial.Polynomial) []Share {
6467
shares := make([]Share, s.n)
6568
x := s.g.NewScalar()
6669
for i := range shares {
6770
id := i + 1
6871
x.SetUint64(uint64(id))
69-
shares[i].ID = uint(id)
72+
shares[i].ID = uint64(id)
7073
shares[i].Value = poly.Evaluate(x)
7174
}
7275

7376
return shares
7477
}
7578

7679
// 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 {
7881
return s.generateShares(s.polyFromSecret(rnd, secret))
7982
}
8083

8184
// Recover returns the secret provided more than t shares are given. Returns an
8285
// error if the number of shares is not above the threshold or goes beyond the
8386
// maximum number of shares.
84-
func (s ss) Recover(shares []Share) (group.Scalar, error) {
87+
func (s SecretSharing) Recover(shares []Share) (group.Scalar, error) {
8588
if l := len(shares); l <= int(s.t) {
8689
return nil, fmt.Errorf("secretsharing: does not reach the threshold %v with %v shares", s.t, l)
8790
} else if l > int(s.n) {
@@ -91,7 +94,7 @@ func (s ss) Recover(shares []Share) (group.Scalar, error) {
9194
x := make([]group.Scalar, s.t+1)
9295
px := make([]group.Scalar, s.t+1)
9396
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)
9598
px[i] = shares[i].Value
9699
}
97100

@@ -103,31 +106,32 @@ func (s ss) Recover(shares []Share) (group.Scalar, error) {
103106

104107
type SharesCommitment = []group.Element
105108

106-
type vss struct{ s ss }
109+
type VerifiableSecretSharing struct{ s SecretSharing }
107110

108111
// NewFeldmanSecretSharing implements a (t,n) Feldman's verifiable secret
109112
// sharing. A (t,n) secret sharing allows to split a secret into n shares, such
110113
// that the secret can be only recovered from any subset of t+1 shares. This
111114
// method is verifiable because once the shares and the secret are committed
112115
// during sharding, one can later verify whether the share was generated
113116
// 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) {
115118
s, err := NewShamirSecretSharing(g, t, n)
116-
return vss{s}, err
119+
return VerifiableSecretSharing{s}, err
117120
}
118121

119122
// 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() }
121124

122125
// 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) {
125130
poly := v.s.polyFromSecret(rnd, secret)
126131
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)))
131135
}
132136

133137
return shares, shareComs
@@ -136,7 +140,7 @@ func (v vss) Shard(rnd io.Reader, secret group.Scalar) ([]Share, SharesCommitmen
136140
// Verify returns true if a share was produced by sharding a secret. It uses
137141
// the share commitments generated by the Shard function to verify this
138142
// property.
139-
func (v vss) Verify(s Share, c SharesCommitment) bool {
143+
func (v VerifiableSecretSharing) Verify(s Share, c SharesCommitment) bool {
140144
if len(c) != int(v.s.t+1) {
141145
return false
142146
}
@@ -145,7 +149,7 @@ func (v vss) Verify(s Share, c SharesCommitment) bool {
145149
sum := v.s.g.NewElement().Set(c[lc])
146150
x := v.s.g.NewScalar()
147151
for i := lc - 1; i >= 0; i-- {
148-
x.SetUint64(uint64(s.ID))
152+
x.SetUint64(s.ID)
149153
sum.Mul(sum, x)
150154
sum.Add(sum, c[i])
151155
}
@@ -156,4 +160,6 @@ func (v vss) Verify(s Share, c SharesCommitment) bool {
156160
// Recover returns the secret provided more than t shares are given. Returns an
157161
// error if the number of shares is not above the threshold (t) or is larger
158162
// 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

Comments
 (0)