Skip to content

Commit

Permalink
Updates after cjpatton's review.
Browse files Browse the repository at this point in the history
  • Loading branch information
armfazh committed Oct 10, 2022
1 parent 28db5bf commit da1ac24
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 37 deletions.
13 changes: 6 additions & 7 deletions math/polynomial/polynomial.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,13 @@ func (p Polynomial) Evaluate(x group.Scalar) group.Scalar {
return px
}

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

// LagrangePolynomial stores a Lagrange polynomial over the set of scalars of a group.
Expand Down
66 changes: 36 additions & 30 deletions secretsharing/ss.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package secretsharing provides methods to split secrets in shares.
// Package secretsharing provides methods to split secrets into shares.
//
// Let n be the number of parties, and t the number of corrupted parties such
// that 0 <= t < n. A (t,n) secret sharing allows to split a secret into n
Expand All @@ -8,8 +8,11 @@
// which relies on Lagrange polynomial interpolation.
//
// The NewFeldmanSecretSharing function creates a Feldman secret sharing [2],
// which extends Shamir's by allowing to verify that a share was honestly
// generated.
// which extends Shamir's by allowing to verify that a share is part of a
// committed secret.
//
// In this implementation, secret sharing is defined over the scalar field of
// a prime order group.
//
// References
//
Expand All @@ -28,11 +31,11 @@ import (

// Share represents a share of a secret.
type Share struct {
ID uint // ID uniquely identifies a share in a secret sharing instance.
ID uint64 // ID uniquely identifies a share in a secret sharing instance.
Value group.Scalar // Value stores the share generated from a secret sharing instance.
}

type ss struct {
type SecretSharing struct {
g group.Group
t, n uint
}
Expand All @@ -41,47 +44,47 @@ type ss struct {
// A (t,n) secret sharing allows to split a secret into n shares, such that the
// secret can be only recovered from any subset of t+1 shares. Returns an error
// if 0 <= t < n does not hold.
func NewShamirSecretSharing(g group.Group, t, n uint) (ss, error) {
func NewShamirSecretSharing(g group.Group, t, n uint) (SecretSharing, error) {
if t >= n {
return ss{}, errors.New("secretsharing: bad parameters")
return SecretSharing{}, errors.New("secretsharing: bad parameters")
}
return ss{g: g, t: t, n: n}, nil
return SecretSharing{g: g, t: t, n: n}, nil
}

// Params returns the t and n parameters of the secret sharing.
func (s ss) Params() (t, n uint) { return s.t, s.n }
func (s SecretSharing) Params() (t, n uint) { return s.t, s.n }

func (s ss) polyFromSecret(rnd io.Reader, secret group.Scalar) (p polynomial.Polynomial) {
func (s SecretSharing) polyFromSecret(rnd io.Reader, secret group.Scalar) (p polynomial.Polynomial) {
c := make([]group.Scalar, s.t+1)
for i := range c {
for i := 1; i < len(c); i++ {
c[i] = s.g.RandomScalar(rnd)
}
c[0].Set(secret)
c[0] = secret.Copy()
return polynomial.New(c)
}

func (s ss) generateShares(poly polynomial.Polynomial) []Share {
func (s SecretSharing) generateShares(poly polynomial.Polynomial) []Share {
shares := make([]Share, s.n)
x := s.g.NewScalar()
for i := range shares {
id := i + 1
x.SetUint64(uint64(id))
shares[i].ID = uint(id)
shares[i].ID = uint64(id)
shares[i].Value = poly.Evaluate(x)
}

return shares
}

// Shard splits the secret into n shares.
func (s ss) Shard(rnd io.Reader, secret group.Scalar) []Share {
func (s SecretSharing) Shard(rnd io.Reader, secret group.Scalar) []Share {
return s.generateShares(s.polyFromSecret(rnd, secret))
}

// Recover returns the secret provided more than t shares are given. Returns an
// error if the number of shares is not above the threshold or goes beyond the
// maximum number of shares.
func (s ss) Recover(shares []Share) (group.Scalar, error) {
func (s SecretSharing) Recover(shares []Share) (group.Scalar, error) {
if l := len(shares); l <= int(s.t) {
return nil, fmt.Errorf("secretsharing: does not reach the threshold %v with %v shares", s.t, l)
} else if l > int(s.n) {
Expand All @@ -91,7 +94,7 @@ func (s ss) Recover(shares []Share) (group.Scalar, error) {
x := make([]group.Scalar, s.t+1)
px := make([]group.Scalar, s.t+1)
for i := range shares[:s.t+1] {
x[i] = s.g.NewScalar().SetUint64(uint64(shares[i].ID))
x[i] = s.g.NewScalar().SetUint64(shares[i].ID)
px[i] = shares[i].Value
}

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

type SharesCommitment = []group.Element

type vss struct{ s ss }
type VerifiableSecretSharing struct{ s SecretSharing }

// NewFeldmanSecretSharing implements a (t,n) Feldman's verifiable secret
// sharing. A (t,n) secret sharing allows to split a secret into n shares, such
// that the secret can be only recovered from any subset of t+1 shares. This
// method is verifiable because once the shares and the secret are committed
// during sharding, one can later verify whether the share was generated
// honestly. Returns an error if 0 < t <= n does not hold.
func NewFeldmanSecretSharing(g group.Group, t, n uint) (vss, error) {
func NewFeldmanSecretSharing(g group.Group, t, n uint) (VerifiableSecretSharing, error) {
s, err := NewShamirSecretSharing(g, t, n)
return vss{s}, err
return VerifiableSecretSharing{s}, err
}

// Params returns the t and n parameters of the secret sharing.
func (v vss) Params() (t, n uint) { return v.s.Params() }
func (v VerifiableSecretSharing) Params() (t, n uint) { return v.s.Params() }

// Shard splits the secret into n shares, and also returns a commitment to both
// the secret and the shares.
func (v vss) Shard(rnd io.Reader, secret group.Scalar) ([]Share, SharesCommitment) {
// the secret and the shares. The ShareCommitment must be sent to each party
// so each party can verify its share is correct. Sharding a secret more
// than once produces ShareCommitments with the same first entry.
func (v VerifiableSecretSharing) Shard(rnd io.Reader, secret group.Scalar) ([]Share, SharesCommitment) {
poly := v.s.polyFromSecret(rnd, secret)
shares := v.s.generateShares(poly)
coeffs := poly.Coefficients()
shareComs := make(SharesCommitment, len(coeffs))
for i := range coeffs {
shareComs[i] = v.s.g.NewElement().MulGen(coeffs[i])
shareComs := make(SharesCommitment, poly.Degree()+1)
for i := range shareComs {
shareComs[i] = v.s.g.NewElement().MulGen(poly.Coefficient(uint(i)))
}

return shares, shareComs
Expand All @@ -136,7 +140,7 @@ func (v vss) Shard(rnd io.Reader, secret group.Scalar) ([]Share, SharesCommitmen
// Verify returns true if a share was produced by sharding a secret. It uses
// the share commitments generated by the Shard function to verify this
// property.
func (v vss) Verify(s Share, c SharesCommitment) bool {
func (v VerifiableSecretSharing) Verify(s Share, c SharesCommitment) bool {
if len(c) != int(v.s.t+1) {
return false
}
Expand All @@ -145,7 +149,7 @@ func (v vss) Verify(s Share, c SharesCommitment) bool {
sum := v.s.g.NewElement().Set(c[lc])
x := v.s.g.NewScalar()
for i := lc - 1; i >= 0; i-- {
x.SetUint64(uint64(s.ID))
x.SetUint64(s.ID)
sum.Mul(sum, x)
sum.Add(sum, c[i])
}
Expand All @@ -156,4 +160,6 @@ func (v vss) Verify(s Share, c SharesCommitment) bool {
// Recover returns the secret provided more than t shares are given. Returns an
// error if the number of shares is not above the threshold (t) or is larger
// than the maximum number of shares (n).
func (v vss) Recover(shares []Share) (group.Scalar, error) { return v.s.Recover(shares) }
func (v VerifiableSecretSharing) Recover(shares []Share) (group.Scalar, error) {
return v.s.Recover(shares)
}

0 comments on commit da1ac24

Please sign in to comment.