Skip to content

Commit

Permalink
Merge a2dd5d7 into 4cfe257
Browse files Browse the repository at this point in the history
  • Loading branch information
Daeinar committed Sep 10, 2018
2 parents 4cfe257 + a2dd5d7 commit d510e55
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 0 deletions.
69 changes: 69 additions & 0 deletions share/poly.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,9 @@ func RecoverCommit(g kyber.Group, shares []*PubShare, t, n int) (kyber.Point, er
continue
}
x[i] = g.Scalar().SetInt64(1 + int64(s.I))
if len(x) == t {
break
}
}

if len(x) < t {
Expand Down Expand Up @@ -426,3 +429,69 @@ func RecoverCommit(g kyber.Group, shares []*PubShare, t, n int) (kyber.Point, er

return Acc, nil
}

// RecoverPubPoly reconstructs the full public polynomial from a set of public
// shares using Lagrange interpolation.
func RecoverPubPoly(g kyber.Group, shares []*PubShare, t, n int) (*PubPoly, error) {
x := make(map[int]kyber.Scalar)
for i, s := range shares {
if s == nil || s.V == nil || s.I < 0 || n <= s.I {
continue
}
x[i] = g.Scalar().SetInt64(1 + int64(s.I))
if len(x) == t {
break
}
}

if len(x) < t {
return nil, errors.New("share: not enough good public shares to reconstruct secret commitment")
}

var accPoly *PubPoly
var err error

num := g.Scalar()
den := g.Scalar()

for j, xj := range x {
var basis = &PriPoly{
g: g,
coeffs: []kyber.Scalar{g.Scalar().One()},
}
// compute lagrange basis l_j
num.One()
den.One()
var acc = g.Scalar().One()
for m, xm := range x {
if j == m {
continue
}
basis = basis.Mul(xMinusConst(g, xm))
den.Sub(xj, xm) // den = xj - xm
den.Inv(den) // den = 1 / den
acc.Mul(acc, den) // acc = acc * den
}

// multiply all coefficients by the denominator
for i := range basis.coeffs {
basis.coeffs[i] = basis.coeffs[i].Mul(basis.coeffs[i], acc)
}

// compute the L_j * y_j polynomial in point space
tmp := basis.Commit(shares[j].V)
if accPoly == nil {
accPoly = tmp
continue
}

// add all L_j * y_j together
accPoly, err = accPoly.Add(tmp)
if err != nil {
return nil, err
}
}

return accPoly, nil

}
133 changes: 133 additions & 0 deletions share/poly_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package share
import (
"testing"

"github.com/dedis/kyber"
"github.com/dedis/kyber/group/edwards25519"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -317,3 +318,135 @@ func TestPriPolyCoefficients(test *testing.T) {
require.Equal(test, a.coeffs, b.coeffs)

}

func TestRefreshDKG(test *testing.T) {
g := edwards25519.NewBlakeSHA256Ed25519()
n := 10
t := n/2 + 1

// Run an n-fold Pedersen VSS (= DKG)
priPolys := make([]*PriPoly, n)
priShares := make([][]*PriShare, n)
pubPolys := make([]*PubPoly, n)
pubShares := make([][]*PubShare, n)
for i := 0; i < n; i++ {
priPolys[i] = NewPriPoly(g, t, nil, g.RandomStream())
priShares[i] = priPolys[i].Shares(n)
pubPolys[i] = priPolys[i].Commit(nil)
pubShares[i] = pubPolys[i].Shares(n)
}

// Verify VSS shares
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
sij := priShares[i][j]
// s_ij * G
sijG := g.Point().Base().Mul(sij.V, nil)
require.True(test, sijG.Equal(pubShares[i][j].V))
}
}

// Create private DKG shares
dkgShares := make([]*PriShare, n)
for i := 0; i < n; i++ {
acc := g.Scalar().Zero()
for j := 0; j < n; j++ { // assuming all participants are in the qualified set
acc = g.Scalar().Add(acc, priShares[j][i].V)
}
dkgShares[i] = &PriShare{i, acc}
}

// Create public DKG commitments (= verification vector)
dkgCommits := make([]kyber.Point, t)
for k := 0; k < t; k++ {
acc := g.Point().Null()
for i := 0; i < n; i++ { // assuming all participants are in the qualified set
_, coeff := pubPolys[i].Info()
acc = g.Point().Add(acc, coeff[k])
}
dkgCommits[k] = acc
}

// Check that the private DKG shares verify against the public DKG commits
dkgPubPoly := NewPubPoly(g, nil, dkgCommits)
for i := 0; i < n; i++ {
require.True(test, dkgPubPoly.Check(dkgShares[i]))
}

// Start verifiable resharing process
subPriPolys := make([]*PriPoly, n)
subPriShares := make([][]*PriShare, n)
subPubPolys := make([]*PubPoly, n)
subPubShares := make([][]*PubShare, n)

// Create subshares and subpolys
for i := 0; i < n; i++ {
subPriPolys[i] = NewPriPoly(g, t, dkgShares[i].V, g.RandomStream())
subPriShares[i] = subPriPolys[i].Shares(n)
subPubPolys[i] = subPriPolys[i].Commit(nil)
subPubShares[i] = subPubPolys[i].Shares(n)
require.True(test, g.Point().Mul(subPriShares[i][0].V, nil).Equal(subPubShares[i][0].V))
}

// Handout shares to new nodes column-wise and verify them
newDKGShares := make([]*PriShare, n)
for i := 0; i < n; i++ {
tmpPriShares := make([]*PriShare, n) // column-wise reshuffled sub-shares
tmpPubShares := make([]*PubShare, n) // public commitments to old DKG private shares
for j := 0; j < n; j++ {
// Check 1: Verify that the received individual private subshares s_ji
// is correct by evaluating the public commitment vector
tmpPriShares[j] = &PriShare{I: j, V: subPriShares[j][i].V} // Shares that participant i gets from j
require.True(test, g.Point().Mul(tmpPriShares[j].V, nil).Equal(subPubPolys[j].Eval(i).V))

// Check 2: Verify that the received sub public shares are
// commitments to the original secret
tmpPubShares[j] = dkgPubPoly.Eval(j)
require.True(test, tmpPubShares[j].V.Equal(subPubPolys[j].Commit()))
}
// Check 3: Verify that the received public shares interpolate to the
// original DKG public key
com, err := RecoverCommit(g, tmpPubShares, t, n)
require.NoError(test, err)
require.True(test, dkgCommits[0].Equal(com))

// Compute the refreshed private DKG share of node i
s, err := RecoverSecret(g, tmpPriShares, t, n)
require.NoError(test, err)
newDKGShares[i] = &PriShare{I: i, V: s}
}

// Refresh the DKG commitments (= verification vector)
newDKGCommits := make([]kyber.Point, t)
for i := 0; i < t; i++ {
pubShares := make([]*PubShare, n)
for j := 0; j < n; j++ {
_, c := subPubPolys[j].Info()
pubShares[j] = &PubShare{I: j, V: c[i]}
}
com, err := RecoverCommit(g, pubShares, t, n)
require.NoError(test, err)
newDKGCommits[i] = com
}

// Check that the old and new DKG public keys are the same
require.True(test, dkgCommits[0].Equal(newDKGCommits[0]))

// Check that the old and new DKG private shares are different
for i := 0; i < n; i++ {
require.False(test, dkgShares[i].V.Equal(newDKGShares[i].V))
}

// Check that the refreshed private DKG shares verify against the refreshed public DKG commits
q := NewPubPoly(g, nil, newDKGCommits)
for i := 0; i < n; i++ {
require.True(test, q.Check(newDKGShares[i]))
}

// Recover the private polynomial
refreshedPriPoly, err := RecoverPriPoly(g, newDKGShares, t, n)
require.NoError(test, err)

// Check that the secret and the corresponding (old) public commit match
require.True(test, g.Point().Mul(refreshedPriPoly.Secret(), nil).Equal(dkgCommits[0]))
}

0 comments on commit d510e55

Please sign in to comment.