diff --git a/README.md b/README.md index 417ee5d..476d41c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ Secret sharing enables to _shard_ (or _split_) a secret key into an arbitrary nu same key with any subset of at minimum _t_ of these key shares in a _(t,n)_-threshold scheme. Note that the key distribution (sharding) algorithm used in this package is a _trusted dealer_ (i.e. centralised). If -you need a truly decentralized key generation, you can use the [dkg package](https://github.com/bytemare/dkg). +you need a truly decentralized key generation, you can use the [dkg package](https://github.com/bytemare/dkg) which +builds on this package. ## Documentation [![Go Reference](https://pkg.go.dev/badge/github.com/bytemare/secret-sharing.svg)](https://pkg.go.dev/github.com/bytemare/secret-sharing) diff --git a/go.mod b/go.mod index 7b95d06..6f8f23e 100644 --- a/go.mod +++ b/go.mod @@ -2,15 +2,15 @@ module github.com/bytemare/secret-sharing go 1.22.2 -require github.com/bytemare/crypto v0.6.0 +require github.com/bytemare/crypto v0.7.0 require ( filippo.io/edwards25519 v1.1.0 // indirect filippo.io/nistec v0.0.3 // indirect github.com/bytemare/hash v0.3.0 // indirect github.com/bytemare/hash2curve v0.3.0 // indirect - github.com/bytemare/secp256k1 v0.1.2 // indirect + github.com/bytemare/secp256k1 v0.1.4 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/sys v0.20.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/sys v0.21.0 // indirect ) diff --git a/go.sum b/go.sum index ebd2ca8..9ee2f5b 100644 --- a/go.sum +++ b/go.sum @@ -2,17 +2,17 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= filippo.io/nistec v0.0.3 h1:h336Je2jRDZdBCLy2fLDUd9E2unG32JLwcJi0JQE9Cw= filippo.io/nistec v0.0.3/go.mod h1:84fxC9mi+MhC2AERXI4LSa8cmSVOzrFikg6hZ4IfCyw= -github.com/bytemare/crypto v0.6.0 h1:wTsJ1jAcCMqDYWP4W2W5wBI36gU9s3nnz1Xmec89n7E= -github.com/bytemare/crypto v0.6.0/go.mod h1:JSO2mlWIuYZHTxeO02xQTf+0tFX9Gue7OsUrEGGYN8Q= +github.com/bytemare/crypto v0.7.0 h1:MbYNWjnuN2NH0ctt2U0HGYoJpxKqKT+c0icvLqRn4i8= +github.com/bytemare/crypto v0.7.0/go.mod h1:ulstTFkY36fP3nRtazyKMlGzWuSB+0/QE38InlSUCX4= github.com/bytemare/hash v0.3.0 h1:RqFMt3mqpF7UxLdjBrsOZm/2cz0cQiAOnYc9gDLopWE= github.com/bytemare/hash v0.3.0/go.mod h1:YKOBchL0l8hRLFinVCL8YUKokGNIMhrWEHPHo3EV7/M= github.com/bytemare/hash2curve v0.3.0 h1:41Npcbc+u/E252A5aCMtxDcz7JPkkX1QzShneTFm4eg= github.com/bytemare/hash2curve v0.3.0/go.mod h1:itj45U8uqvCtWC0eCswIHVHswXcEHkpFui7gfJdPSfQ= -github.com/bytemare/secp256k1 v0.1.2 h1:aM+p/+0y1h0SZWqS/yzjGPzffVFubJvwLjUgodFEWOo= -github.com/bytemare/secp256k1 v0.1.2/go.mod h1:Pxb9miDs8PTt5mOktvvXiRflvLxI1wdxbXrc6IYsaho= +github.com/bytemare/secp256k1 v0.1.4 h1:6F1yP6RiUiWwH7AsGHsHktmHm24QcetdDcc39roBd2M= +github.com/bytemare/secp256k1 v0.1.4/go.mod h1:Pxb9miDs8PTt5mOktvvXiRflvLxI1wdxbXrc6IYsaho= github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= diff --git a/polynomial.go b/polynomial.go index a87e6b8..78e8926 100644 --- a/polynomial.go +++ b/polynomial.go @@ -127,7 +127,7 @@ func (p Polynomial) hasDuplicates() bool { // Evaluate evaluates the polynomial p at point x using Horner's method. func (p Polynomial) Evaluate(x *group.Scalar) *group.Scalar { - // since value starts with 0, we can skip multiplying by x, and start from the end + // since value is an accumulator and starts with 0, we can skip multiplying by x, and start from the end value := p[len(p)-1].Copy() for i := len(p) - 2; i >= 0; i-- { value.Multiply(x) @@ -164,13 +164,13 @@ func (p Polynomial) DeriveInterpolatingValue(g group.Group, id *group.Scalar) (* func PolynomialInterpolateConstant(g group.Group, shares []*KeyShare) (*group.Scalar, error) { xCoords := make(Polynomial, len(shares)) for i, share := range shares { - xCoords[i] = share.Identifier + xCoords[i] = g.NewScalar().SetUInt64(share.Identifier) } constant := g.NewScalar().Zero() - for _, share := range shares { - iv, err := xCoords.DeriveInterpolatingValue(g, share.Identifier) + for i, share := range shares { + iv, err := xCoords.DeriveInterpolatingValue(g, xCoords[i]) if err != nil { return nil, err } diff --git a/sharing.go b/sharing.go index 23bed95..1cc9c75 100644 --- a/sharing.go +++ b/sharing.go @@ -11,7 +11,6 @@ package secretsharing import ( "errors" - "math/big" group "github.com/bytemare/crypto" ) @@ -26,11 +25,11 @@ var ( // KeyShare identifies the sharded key share for a given participant. type KeyShare struct { - // Identifier uniquely identifies a key share within secret sharing instance. - Identifier *group.Scalar - // SecretKey is the participant's secret share. SecretKey *group.Scalar + + // Identifier uniquely identifies a key share within secret sharing instance. + Identifier uint64 } // Shard splits the secret into total shares, recoverable by a subset of threshold shares. This is the function you @@ -76,10 +75,10 @@ func ShardReturnPolynomial( // Evaluate the polynomial for each point x=1,...,n secretKeyShares := make([]*KeyShare, total) - for i := uint(1); i <= total; i++ { - id := integerToScalar(secret.Copy(), i) + for i := uint64(1); i <= uint64(total); i++ { + id := g.NewScalar().SetUInt64(i) yi := p.Evaluate(id) - secretKeyShares[i-1] = &KeyShare{id, yi} + secretKeyShares[i-1] = &KeyShare{Identifier: i, SecretKey: yi} } return secretKeyShares, p, nil @@ -120,12 +119,3 @@ func makePolynomial(g group.Group, threshold uint, polynomial ...*group.Scalar) return p, nil } - -// integerToScalar creates a group.Scalar given an int. -func integerToScalar(target *group.Scalar, i uint) *group.Scalar { - if err := target.SetInt(big.NewInt(int64(i))); err != nil { - panic(err) - } - - return target -} diff --git a/tests/ss_test.go b/tests/ss_test.go index f812561..2dca636 100644 --- a/tests/ss_test.go +++ b/tests/ss_test.go @@ -59,9 +59,9 @@ func TestSecretSharing(t *testing.T) { t.Fatal("expected error on too few shares") } - // it must not succeed with threshold shares + // it must succeed with threshold shares if err, _ = testCombine(g, secret, shares[0], shares[1], shares[3]); err != nil { - t.Fatal("expected error on too few shares") + t.Fatalf("unexpected error on threshold number of shares: %v", err) } // it must succeed with more than threshold shares @@ -181,11 +181,11 @@ func TestVerify_BadCommitments(t *testing.T) { } // Test without commitments - if secretsharing.Verify(g, nil, nil, nil) { + if secretsharing.Verify(g, 0, nil, nil) { t.Fatalf("verification succeeded but shouldn't") } - if secretsharing.Verify(g, nil, nil, make(secretsharing.Commitment, 0)) { + if secretsharing.Verify(g, 0, nil, make(secretsharing.Commitment, 0)) { t.Fatalf("verification succeeded but shouldn't") } }) @@ -371,7 +371,7 @@ func TestCombine_BadIdentifiers_NilZero_1(t *testing.T) { for _, g := range groups { badShare := []*secretsharing.KeyShare{ { - Identifier: nil, + Identifier: 0, SecretKey: nil, }, } @@ -385,18 +385,8 @@ func TestCombine_BadIdentifiers_Nil(t *testing.T) { expected := "the polynomial has a nil coefficient" for _, g := range groups { - - badShare := []*secretsharing.KeyShare{ - { - Identifier: g.NewScalar().One(), - SecretKey: g.NewScalar().Random(), - }, - { - Identifier: nil, - SecretKey: g.NewScalar().Random(), - }, - } - if _, err := secretsharing.PolynomialInterpolateConstant(g, badShare); err == nil || err.Error() != expected { + xCoords := secretsharing.Polynomial{g.NewScalar().SetUInt64(1), nil} + if _, err := xCoords.DeriveInterpolatingValue(g, xCoords[0]); err == nil || err.Error() != expected { t.Fatalf("expected error %q, got %q", expected, err) } } @@ -409,11 +399,11 @@ func TestCombine_BadIdentifiers_Zero(t *testing.T) { badShare := []*secretsharing.KeyShare{ { - Identifier: g.NewScalar().One(), + Identifier: 1, SecretKey: g.NewScalar().Random(), }, { - Identifier: g.NewScalar().Zero(), + Identifier: 0, SecretKey: g.NewScalar().Random(), }, } @@ -430,11 +420,11 @@ func TestCombine_BadIdentifiers_Duplicates(t *testing.T) { badShare := []*secretsharing.KeyShare{ { - Identifier: g.NewScalar().One(), + Identifier: 1, SecretKey: g.NewScalar().Random(), }, { - Identifier: g.NewScalar().One(), + Identifier: 1, SecretKey: g.NewScalar().Random(), }, } diff --git a/verifiable.go b/verifiable.go index 704ea62..932059a 100644 --- a/verifiable.go +++ b/verifiable.go @@ -28,11 +28,12 @@ func Commit(g group.Group, polynomial Polynomial) Commitment { // Verify allows verification of a participant's secret share given its public key and the VSS commitment // to the secret polynomial. -func Verify(g group.Group, id *group.Scalar, pk *group.Element, coms Commitment) bool { +func Verify(g group.Group, id uint64, pk *group.Element, coms Commitment) bool { if len(coms) == 0 { return false } + ids := g.NewScalar().SetUInt64(id) prime := coms[0].Copy() one := g.NewScalar().One() j := g.NewScalar().One() @@ -40,13 +41,13 @@ func Verify(g group.Group, id *group.Scalar, pk *group.Element, coms Commitment) switch { // If id == 1 we can spare exponentiation and multiplications - case id.Equal(one) == 1: + case id == 1: for _, com := range coms[1:] { prime.Add(com) } case len(coms) >= 2: // if there are elements left and since j == 1, we can spare one exponentiation - prime.Add(coms[1].Copy().Multiply(id)) + prime.Add(coms[1].Copy().Multiply(ids)) j.Add(one) i++ @@ -54,7 +55,7 @@ func Verify(g group.Group, id *group.Scalar, pk *group.Element, coms Commitment) fallthrough default: for _, com := range coms[i:] { - prime.Add(com.Copy().Multiply(id.Copy().Pow(j))) + prime.Add(com.Copy().Multiply(ids.Copy().Pow(j))) j.Add(one) } }