diff --git a/CHANGELOG.md b/CHANGELOG.md index 406c3a2c..e53de43e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ All notable changes to this repo will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v1.5.4 +- Export Value in ElGamal Public Keys + ## v1.5.3 - Address Alpha-Rays attack on GG20 DKG https://eprint.iacr.org/2021/1621.pdf diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..2f51484e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.17 AS builder +# Install gomarkdoc +RUN GO111MODULE=on go get -u github.com/princjef/gomarkdoc/cmd/gomarkdoc + +# Install rust and build spdx +COPY . /kryptology +WORKDIR /kryptology + +RUN apt update && apt install -y curl +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -- | sh -s -- -y +RUN /root/.cargo/bin/cargo build --release --manifest-path=./cmd/spdx/Cargo.toml && \ + cp ./cmd/spdx/target/release/spdx /usr/bin/ && \ + chmod 755 /usr/bin/spdx diff --git a/pkg/core/curves/native/bls12-381/arithmetic_decl.go b/pkg/core/curves/native/bls12-381/arithmetic_decl.go index c1d839de..20cb292b 100644 --- a/pkg/core/curves/native/bls12-381/arithmetic_decl.go +++ b/pkg/core/curves/native/bls12-381/arithmetic_decl.go @@ -3,7 +3,7 @@ // // SPDX-License-Identifier: Apache-2.0 // - +//go:build amd64 && !generic // +build amd64,!generic package bls12381 diff --git a/pkg/core/curves/native/bls12-381/arithmetic_fallback.go b/pkg/core/curves/native/bls12-381/arithmetic_fallback.go index 73e931fd..7741c59a 100644 --- a/pkg/core/curves/native/bls12-381/arithmetic_fallback.go +++ b/pkg/core/curves/native/bls12-381/arithmetic_fallback.go @@ -4,7 +4,8 @@ // SPDX-License-Identifier: Apache-2.0 // -// +build !amd64 generic +//go:build !amd64 && generic +// +build !amd64,generic // Native go field arithmetic code is generated with 'goff' // https://github.com/ConsenSys/goff diff --git a/pkg/dkg/frost/README.md b/pkg/dkg/frost/README.md index 97f902dd..92a02fb4 100755 --- a/pkg/dkg/frost/README.md +++ b/pkg/dkg/frost/README.md @@ -14,6 +14,9 @@ import "github.com/coinbase/kryptology/pkg/dkg/frost" - [func (dp *DkgParticipant) Round2(bcast map[uint32]*Round1Bcast, p2psend map[uint32]*sharing.ShamirShare) (*Round2Bcast, error)](<#func-dkgparticipant-round2>) - [type Round1Bcast](<#type-round1bcast>) - [type Round1P2PSend](<#type-round1p2psend>) +- [type Round1Result](<#type-round1result>) + - [func (result *Round1Result) Decode(input []byte) error](<#func-round1result-decode>) + - [func (result *Round1Result) Encode() ([]byte, error)](<#func-round1result-encode>) - [type Round2Bcast](<#type-round2bcast>) @@ -72,6 +75,27 @@ Round1P2PSend are values that are P2PSend to all other participants after round1 type Round1P2PSend = map[uint32]*sharing.ShamirShare ``` +## type [Round1Result]() + +```go +type Round1Result struct { + Broadcast *Round1Bcast + P2P *sharing.ShamirShare +} +``` + +### func \(\*Round1Result\) [Decode]() + +```go +func (result *Round1Result) Decode(input []byte) error +``` + +### func \(\*Round1Result\) [Encode]() + +```go +func (result *Round1Result) Encode() ([]byte, error) +``` + ## type [Round2Bcast]() Round2Bcast are values that are broadcast to all other participants after round2 completes diff --git a/pkg/dkg/frost/dkg_round1.go b/pkg/dkg/frost/dkg_round1.go index df6459c5..457c50f8 100644 --- a/pkg/dkg/frost/dkg_round1.go +++ b/pkg/dkg/frost/dkg_round1.go @@ -7,11 +7,14 @@ package frost import ( + "bytes" crand "crypto/rand" + "encoding/gob" "fmt" "github.com/coinbase/kryptology/internal" "github.com/coinbase/kryptology/pkg/core/curves" "github.com/coinbase/kryptology/pkg/sharing" + "github.com/pkg/errors" "reflect" ) @@ -22,6 +25,31 @@ type Round1Bcast struct { Wi, Ci curves.Scalar } +type Round1Result struct { + Broadcast *Round1Bcast + P2P *sharing.ShamirShare +} + +func (result *Round1Result) Encode() ([]byte, error) { + gob.Register(result.Broadcast.Verifiers.Commitments[0]) // just the point for now + gob.Register(result.Broadcast.Ci) + buf := &bytes.Buffer{} + enc := gob.NewEncoder(buf) + if err := enc.Encode(result); err != nil { + return nil, errors.Wrap(err, "couldn't encode round 1 broadcast") + } + return buf.Bytes(), nil +} + +func (result *Round1Result) Decode(input []byte) error { + buf := bytes.NewBuffer(input) + dec := gob.NewDecoder(buf) + if err := dec.Decode(result); err != nil { + return errors.Wrap(err, "couldn't encode round 1 broadcast") + } + return nil +} + // Round1P2PSend are values that are P2PSend to all other participants // after round1 completes type Round1P2PSend = map[uint32]*sharing.ShamirShare diff --git a/pkg/sharing/README.md b/pkg/sharing/README.md index 7561f059..d42355dc 100755 --- a/pkg/sharing/README.md +++ b/pkg/sharing/README.md @@ -32,7 +32,7 @@ import "github.com/coinbase/kryptology/pkg/sharing" - [func NewShamir(threshold, limit uint32, curve *curves.Curve) (*Shamir, error)](<#func-newshamir>) - [func (s Shamir) Combine(shares ...*ShamirShare) (curves.Scalar, error)](<#func-shamir-combine>) - [func (s Shamir) CombinePoints(shares ...*ShamirShare) (curves.Point, error)](<#func-shamir-combinepoints>) - - [func (s Shamir) LagrangeCoeffs(shares map[uint32]*ShamirShare) (map[uint32]curves.Scalar, error)](<#func-shamir-lagrangecoeffs>) + - [func (s Shamir) LagrangeCoeffs(identities []uint32) (map[uint32]curves.Scalar, error)](<#func-shamir-lagrangecoeffs>) - [func (s Shamir) Split(secret curves.Scalar, reader io.Reader) ([]*ShamirShare, error)](<#func-shamir-split>) - [type ShamirShare](<#type-shamirshare>) - [func (ss ShamirShare) Bytes() []byte](<#func-shamirshare-bytes>) diff --git a/pkg/sharing/feldman.go b/pkg/sharing/feldman.go index 63522459..b8aef7aa 100644 --- a/pkg/sharing/feldman.go +++ b/pkg/sharing/feldman.go @@ -85,7 +85,11 @@ func (f Feldman) LagrangeCoeffs(shares map[uint32]*ShamirShare) (map[uint32]curv limit: f.Limit, curve: f.Curve, } - return shamir.LagrangeCoeffs(shares) + identities := make([]uint32, 0) + for _, xi := range shares { + identities = append(identities, xi.Id) + } + return shamir.LagrangeCoeffs(identities) } func (f Feldman) Combine(shares ...*ShamirShare) (curves.Scalar, error) { diff --git a/pkg/sharing/pedersen.go b/pkg/sharing/pedersen.go index fbcd72af..bf3be802 100644 --- a/pkg/sharing/pedersen.go +++ b/pkg/sharing/pedersen.go @@ -125,7 +125,11 @@ func (pd Pedersen) LagrangeCoeffs(shares map[uint32]*ShamirShare) (map[uint32]cu limit: pd.limit, curve: pd.curve, } - return shamir.LagrangeCoeffs(shares) + identities := make([]uint32, 0) + for _, xi := range shares { + identities = append(identities, xi.Id) + } + return shamir.LagrangeCoeffs(identities) } func (pd Pedersen) Combine(shares ...*ShamirShare) (curves.Scalar, error) { diff --git a/pkg/sharing/shamir.go b/pkg/sharing/shamir.go index 5788f6fb..a83d75b6 100644 --- a/pkg/sharing/shamir.go +++ b/pkg/sharing/shamir.go @@ -80,13 +80,13 @@ func (s Shamir) getPolyAndShares(secret curves.Scalar, reader io.Reader) ([]*Sha return shares, poly } -func (s Shamir) LagrangeCoeffs(shares map[uint32]*ShamirShare) (map[uint32]curves.Scalar, error) { - xs := make(map[uint32]curves.Scalar, len(shares)) - for i, xi := range shares { - xs[i] = s.curve.Scalar.New(int(xi.Id)) +func (s Shamir) LagrangeCoeffs(identities []uint32) (map[uint32]curves.Scalar, error) { + xs := make(map[uint32]curves.Scalar, len(identities)) + for _, xi := range identities { + xs[xi] = s.curve.Scalar.New(int(xi)) } - result := make(map[uint32]curves.Scalar, len(shares)) + result := make(map[uint32]curves.Scalar, len(identities)) for i, xi := range xs { num := s.curve.Scalar.One() den := s.curve.Scalar.One() diff --git a/pkg/sharing/shamir_test.go b/pkg/sharing/shamir_test.go index 53626228..c2317466 100644 --- a/pkg/sharing/shamir_test.go +++ b/pkg/sharing/shamir_test.go @@ -108,7 +108,11 @@ func TestShamirComputeL(t *testing.T) { shares, err := scheme.Split(secret, crand.Reader) assert.Nil(t, err) assert.NotNil(t, shares) - lCoeffs, err := scheme.LagrangeCoeffs(map[uint32]*ShamirShare{1: shares[0], 2: shares[1]}) + identities := make([]uint32, 0) + for _, xi := range shares { + identities = append(identities, xi.Id) + } + lCoeffs, err := scheme.LagrangeCoeffs(identities) assert.Nil(t, err) assert.NotNil(t, lCoeffs) diff --git a/pkg/signatures/bls/bls_sig/lib.go b/pkg/signatures/bls/bls_sig/lib.go index 82a2214d..cff8c581 100644 --- a/pkg/signatures/bls/bls_sig/lib.go +++ b/pkg/signatures/bls/bls_sig/lib.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/lib_test.go b/pkg/signatures/bls/bls_sig/lib_test.go index cdd8bee5..fd7ade9d 100644 --- a/pkg/signatures/bls/bls_sig/lib_test.go +++ b/pkg/signatures/bls/bls_sig/lib_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/tiny_bls.go b/pkg/signatures/bls/bls_sig/tiny_bls.go index a61b88df..569b6162 100644 --- a/pkg/signatures/bls/bls_sig/tiny_bls.go +++ b/pkg/signatures/bls/bls_sig/tiny_bls.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/tiny_bls_sig.go b/pkg/signatures/bls/bls_sig/tiny_bls_sig.go index 409985d8..00e298c7 100644 --- a/pkg/signatures/bls/bls_sig/tiny_bls_sig.go +++ b/pkg/signatures/bls/bls_sig/tiny_bls_sig.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/tiny_bls_sig_aug_test.go b/pkg/signatures/bls/bls_sig/tiny_bls_sig_aug_test.go index ca32d88b..1b245c38 100644 --- a/pkg/signatures/bls/bls_sig/tiny_bls_sig_aug_test.go +++ b/pkg/signatures/bls/bls_sig/tiny_bls_sig_aug_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/tiny_bls_sig_basic_test.go b/pkg/signatures/bls/bls_sig/tiny_bls_sig_basic_test.go index 6979a5ee..b3032e57 100644 --- a/pkg/signatures/bls/bls_sig/tiny_bls_sig_basic_test.go +++ b/pkg/signatures/bls/bls_sig/tiny_bls_sig_basic_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/tiny_bls_sig_pop_test.go b/pkg/signatures/bls/bls_sig/tiny_bls_sig_pop_test.go index 096953aa..4262b181 100644 --- a/pkg/signatures/bls/bls_sig/tiny_bls_sig_pop_test.go +++ b/pkg/signatures/bls/bls_sig/tiny_bls_sig_pop_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/usual_bls.go b/pkg/signatures/bls/bls_sig/usual_bls.go index 15be0529..61b7b1a1 100644 --- a/pkg/signatures/bls/bls_sig/usual_bls.go +++ b/pkg/signatures/bls/bls_sig/usual_bls.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/usual_bls_sig.go b/pkg/signatures/bls/bls_sig/usual_bls_sig.go index c2937448..68498e49 100644 --- a/pkg/signatures/bls/bls_sig/usual_bls_sig.go +++ b/pkg/signatures/bls/bls_sig/usual_bls_sig.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/usual_bls_sig_aug_test.go b/pkg/signatures/bls/bls_sig/usual_bls_sig_aug_test.go index 188e823f..9b6ab646 100644 --- a/pkg/signatures/bls/bls_sig/usual_bls_sig_aug_test.go +++ b/pkg/signatures/bls/bls_sig/usual_bls_sig_aug_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/usual_bls_sig_basic_test.go b/pkg/signatures/bls/bls_sig/usual_bls_sig_basic_test.go index 8cc858ca..17a05906 100644 --- a/pkg/signatures/bls/bls_sig/usual_bls_sig_basic_test.go +++ b/pkg/signatures/bls/bls_sig/usual_bls_sig_basic_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/bls_sig/usual_bls_sig_pop_test.go b/pkg/signatures/bls/bls_sig/usual_bls_sig_pop_test.go index 0eed2335..15154ec8 100644 --- a/pkg/signatures/bls/bls_sig/usual_bls_sig_pop_test.go +++ b/pkg/signatures/bls/bls_sig/usual_bls_sig_pop_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package bls_sig import ( diff --git a/pkg/signatures/bls/finitefield/finitefield.go b/pkg/signatures/bls/finitefield/finitefield.go index c783b2d9..ebb35757 100644 --- a/pkg/signatures/bls/finitefield/finitefield.go +++ b/pkg/signatures/bls/finitefield/finitefield.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + /* Package finitefield provides a finite field type (Field) that wraps big.Int operations and verifies that all mutations to the value are done within the field. diff --git a/pkg/signatures/bls/finitefield/finitefield_test.go b/pkg/signatures/bls/finitefield/finitefield_test.go index e32156a8..e1b82d50 100644 --- a/pkg/signatures/bls/finitefield/finitefield_test.go +++ b/pkg/signatures/bls/finitefield/finitefield_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package finitefield import ( diff --git a/pkg/signatures/bls/rust/src/main.rs b/pkg/signatures/bls/rust/src/main.rs index 1a3d8722..8b649b93 100644 --- a/pkg/signatures/bls/rust/src/main.rs +++ b/pkg/signatures/bls/rust/src/main.rs @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + use bls_sigs_ref::BLSSignaturePop; use miracl_core::{ bls12381::{ diff --git a/pkg/signatures/bls/shamir/shamir.go b/pkg/signatures/bls/shamir/shamir.go index 30191726..bb76dad5 100644 --- a/pkg/signatures/bls/shamir/shamir.go +++ b/pkg/signatures/bls/shamir/shamir.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + /* Package shamir is a port of the hashicorp/vault implementation of Shamir's Secret Sharing which has been modified to work with a finite field rather than arbitrary length content. diff --git a/pkg/signatures/bls/shamir/shamir_test.go b/pkg/signatures/bls/shamir/shamir_test.go index 00ecb61b..27decd3b 100644 --- a/pkg/signatures/bls/shamir/shamir_test.go +++ b/pkg/signatures/bls/shamir/shamir_test.go @@ -1,3 +1,9 @@ +// +// Copyright Coinbase, Inc. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + package shamir import ( diff --git a/pkg/ted25519/frost/README.md b/pkg/ted25519/frost/README.md index 9692d424..45e2ad45 100755 --- a/pkg/ted25519/frost/README.md +++ b/pkg/ted25519/frost/README.md @@ -12,13 +12,19 @@ import "github.com/coinbase/kryptology/pkg/ted25519/frost" - [type Ed25519ChallengeDeriver](<#type-ed25519challengederiver>) - [func (ed Ed25519ChallengeDeriver) DeriveChallenge(msg []byte, pubKey curves.Point, r curves.Point) (curves.Scalar, error)](<#func-ed25519challengederiver-derivechallenge>) - [type Round1Bcast](<#type-round1bcast>) + - [func (result *Round1Bcast) Decode(input []byte) error](<#func-round1bcast-decode>) + - [func (result *Round1Bcast) Encode() ([]byte, error)](<#func-round1bcast-encode>) - [type Round2Bcast](<#type-round2bcast>) + - [func (result *Round2Bcast) Decode(input []byte) error](<#func-round2bcast-decode>) + - [func (result *Round2Bcast) Encode() ([]byte, error)](<#func-round2bcast-encode>) - [type Round3Bcast](<#type-round3bcast>) +- [type Signature](<#type-signature>) - [type Signer](<#type-signer>) - [func NewSigner(info *frost.DkgParticipant, id, thresh uint32, lcoeffs map[uint32]curves.Scalar, cosigners []uint32, challengeDeriver ChallengeDerive) (*Signer, error)](<#func-newsigner>) - [func (signer *Signer) SignRound1() (*Round1Bcast, error)](<#func-signer-signround1>) - [func (signer *Signer) SignRound2(msg []byte, round2Input map[uint32]*Round1Bcast) (*Round2Bcast, error)](<#func-signer-signround2>) - [func (signer *Signer) SignRound3(round3Input map[uint32]*Round2Bcast) (*Round3Bcast, error)](<#func-signer-signround3>) + - [func (signer *Signer) Verify(vk curves.Point, message []byte, signature *Signature) (bool, error)](<#func-signer-verify>) ## type [ChallengeDerive]() @@ -51,16 +57,41 @@ type Round1Bcast struct { } ``` -## type [Round2Bcast]() +### func \(\*Round1Bcast\) [Decode]() + +```go +func (result *Round1Bcast) Decode(input []byte) error +``` + +### func \(\*Round1Bcast\) [Encode]() + +```go +func (result *Round1Bcast) Encode() ([]byte, error) +``` + +## type [Round2Bcast]() Round2Bcast contains values that will be broadcast to other signers after completion of round 2\. ```go type Round2Bcast struct { - // contains filtered or unexported fields + Zi curves.Scalar + Vki curves.Point } ``` +### func \(\*Round2Bcast\) [Decode]() + +```go +func (result *Round2Bcast) Decode(input []byte) error +``` + +### func \(\*Round2Bcast\) [Encode]() + +```go +func (result *Round2Bcast) Encode() ([]byte, error) +``` + ## type [Round3Bcast]() Round3Bcast contains the output of FROST signature\, i\.e\.\, it contains FROST signature \(z\,c\) and the corresponding message msg\. @@ -73,6 +104,17 @@ type Round3Bcast struct { } ``` +## type [Signature]() + +Define frost signature type + +```go +type Signature struct { + Z curves.Scalar + C curves.Scalar +} +``` + ## type [Signer]() Signer is a tSchnorr player performing the signing operation\. @@ -111,6 +153,14 @@ SignRound2 implements FROST signing round 2\. func (signer *Signer) SignRound3(round3Input map[uint32]*Round2Bcast) (*Round3Bcast, error) ``` +### func \(\*Signer\) [Verify]() + +```go +func (signer *Signer) Verify(vk curves.Point, message []byte, signature *Signature) (bool, error) +``` + +Method to verify a frost signature\. + Generated by [gomarkdoc]() diff --git a/pkg/ted25519/frost/round1.go b/pkg/ted25519/frost/round1.go index c8ae9a62..48b54d51 100644 --- a/pkg/ted25519/frost/round1.go +++ b/pkg/ted25519/frost/round1.go @@ -7,9 +7,12 @@ package frost import ( + "bytes" crand "crypto/rand" + "encoding/gob" "github.com/coinbase/kryptology/internal" "github.com/coinbase/kryptology/pkg/core/curves" + "github.com/pkg/errors" ) // Round1Bcast contains values to be broadcast to all players after the completion of signing round 1. @@ -17,6 +20,26 @@ type Round1Bcast struct { Di, Ei curves.Point } +func (result *Round1Bcast) Encode() ([]byte, error) { + gob.Register(result.Di) // just the point for now + gob.Register(result.Ei) + buf := &bytes.Buffer{} + enc := gob.NewEncoder(buf) + if err := enc.Encode(result); err != nil { + return nil, errors.Wrap(err, "couldn't encode round 1 broadcast") + } + return buf.Bytes(), nil +} + +func (result *Round1Bcast) Decode(input []byte) error { + buf := bytes.NewBuffer(input) + dec := gob.NewDecoder(buf) + if err := dec.Decode(result); err != nil { + return errors.Wrap(err, "couldn't encode round 1 broadcast") + } + return nil +} + func (signer *Signer) SignRound1() (*Round1Bcast, error) { // Make sure signer is not empty if signer == nil || signer.curve == nil { diff --git a/pkg/ted25519/frost/round2.go b/pkg/ted25519/frost/round2.go index 64f7503d..470ca4f4 100644 --- a/pkg/ted25519/frost/round2.go +++ b/pkg/ted25519/frost/round2.go @@ -7,15 +7,38 @@ package frost import ( + "bytes" + "encoding/gob" "fmt" "github.com/coinbase/kryptology/internal" "github.com/coinbase/kryptology/pkg/core/curves" + "github.com/pkg/errors" ) // Round2Bcast contains values that will be broadcast to other signers after completion of round 2. type Round2Bcast struct { - zi curves.Scalar - vki curves.Point + Zi curves.Scalar + Vki curves.Point +} + +func (result *Round2Bcast) Encode() ([]byte, error) { + gob.Register(result.Zi) + gob.Register(result.Vki) // just the point for now + buf := &bytes.Buffer{} + enc := gob.NewEncoder(buf) + if err := enc.Encode(result); err != nil { + return nil, errors.Wrap(err, "couldn't encode round 1 broadcast") + } + return buf.Bytes(), nil +} + +func (result *Round2Bcast) Decode(input []byte) error { + buf := bytes.NewBuffer(input) + dec := gob.NewDecoder(buf) + if err := dec.Decode(result); err != nil { + return errors.Wrap(err, "couldn't encode round 1 broadcast") + } + return nil } // SignRound2 implements FROST signing round 2. diff --git a/pkg/ted25519/frost/round3.go b/pkg/ted25519/frost/round3.go index 1ae36304..4b82bf06 100644 --- a/pkg/ted25519/frost/round3.go +++ b/pkg/ted25519/frost/round3.go @@ -20,6 +20,12 @@ type Round3Bcast struct { msg []byte } +// Define frost signature type +type Signature struct { + Z curves.Scalar + C curves.Scalar +} + func (signer *Signer) SignRound3(round3Input map[uint32]*Round2Bcast) (*Round3Bcast, error) { // Make sure signer is not empty if signer == nil || signer.curve == nil { @@ -66,8 +72,8 @@ func (signer *Signer) SignRound3(round3Input map[uint32]*Round2Bcast) (*Round3Bc z := signer.curve.NewScalar() negate := signer.state.sumR.IsNegative() for id, data := range round3Input { - zj := data.zi - vkj := data.vki + zj := data.Zi + vkj := data.Vki // Step 2: Verify zj*G = Rj + c*Lj*vkj // zj*G @@ -122,3 +128,28 @@ func (signer *Signer) SignRound3(round3Input map[uint32]*Round2Bcast) (*Round3Bc signer.state.msg, }, nil } + +// Method to verify a frost signature. +func (signer *Signer) Verify(vk curves.Point, message []byte, signature *Signature) (bool, error) { + if vk == nil || message == nil || signature.Z == nil || signature.C == nil { + return false, fmt.Errorf("invalid input!") + } + z := signature.Z + c := signature.C + // R' = z*G + (-c)*vk + zG := signer.curve.ScalarBaseMult(z) + cvk := vk.Mul(c.Neg()) + tempR := zG.Add(cvk) + // Step 6 - c' = H(m, R') + tempC, err := signer.challengeDeriver.DeriveChallenge(signer.state.msg, signer.verificationKey, tempR) + if err != nil { + return false, err + } + + // Step 7 - Check c = c' + if tempC.Cmp(c) != 0 { + return false, fmt.Errorf("invalid signature: c != c'") + } + + return true, nil +} diff --git a/pkg/ted25519/frost/rounds_test.go b/pkg/ted25519/frost/rounds_test.go index 3d142d54..4a4cb9a8 100644 --- a/pkg/ted25519/frost/rounds_test.go +++ b/pkg/ted25519/frost/rounds_test.go @@ -49,11 +49,8 @@ func TestSignRound1Works(t *testing.T) { require.NotNil(t, p2) scheme, _ := sharing.NewShamir(2, 2, testCurve) - lCoeffs, _ := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - p1.Id: {Id: p1.Id, Value: p1.SkShare.Bytes()}, - p2.Id: {Id: p2.Id, Value: p2.SkShare.Bytes()}, - }) - + lCoeffs, err := scheme.LagrangeCoeffs([]uint32{p1.Id, p2.Id}) + require.NoError(t, err) signer1, err := NewSigner(p1, 1, 2, lCoeffs, []uint32{1, 2}, &Ed25519ChallengeDeriver{}) require.NoError(t, err) round1Out, _ := signer1.SignRound1() @@ -70,12 +67,10 @@ func TestSignRound1Works(t *testing.T) { func TestSignRound1RepeatCall(t *testing.T) { p1, p2 := PrepareDkgOutput(t) scheme, _ := sharing.NewShamir(2, 2, testCurve) - lCoeffs, _ := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - p1.Id: {Id: p1.Id, Value: p1.SkShare.Bytes()}, - p2.Id: {Id: p2.Id, Value: p2.SkShare.Bytes()}, - }) + lCoeffs, err := scheme.LagrangeCoeffs([]uint32{p1.Id, p2.Id}) + require.NoError(t, err) signer1, _ := NewSigner(p1, 1, 2, lCoeffs, []uint32{1, 2}, &Ed25519ChallengeDeriver{}) - _, err := signer1.SignRound1() + _, err = signer1.SignRound1() require.NoError(t, err) _, err = signer1.SignRound1() require.Error(t, err) @@ -90,10 +85,7 @@ func PrepareNewSigners(t *testing.T) (*Signer, *Signer) { // field = sharing.NewField(p1.curve.Params().N) require.NotNil(t, scheme) require.NoError(t, err) - lCoeffs, err := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - p1.Id: {Id: p1.Id, Value: p1.SkShare.Bytes()}, - p2.Id: {Id: p2.Id, Value: p2.SkShare.Bytes()}, - }) + lCoeffs, err := scheme.LagrangeCoeffs([]uint32{p1.Id, p2.Id}) require.NotNil(t, lCoeffs[1]) require.NotNil(t, lCoeffs[2]) require.NoError(t, err) @@ -224,10 +216,7 @@ func PrepareRound3Input(t *testing.T) (*Signer, *Signer, map[uint32]*Round2Bcast scheme, err := sharing.NewShamir(threshold, limit, testCurve) require.NotNil(t, scheme) require.NoError(t, err) - lCoeffs, err := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - p1.Id: {Id: p1.Id, Value: p1.SkShare.Bytes()}, - p2.Id: {Id: p2.Id, Value: p2.SkShare.Bytes()}, - }) + lCoeffs, err := scheme.LagrangeCoeffs([]uint32{p1.Id, p2.Id}) require.NotNil(t, lCoeffs[1]) require.NotNil(t, lCoeffs[2]) require.NoError(t, err) @@ -266,6 +255,21 @@ func TestSignRound3Works(t *testing.T) { // signer1 and signer2 outputs the same signature require.Equal(t, round3Out1.Z, round3Out2.Z) require.Equal(t, round3Out1.C, round3Out2.C) + + // test verify method + msg := []byte("message") + signature := &Signature{ + round3Out1.Z, + round3Out1.C, + } + vk := signer1.verificationKey + ok, err := signer1.Verify(vk, msg, signature) + require.True(t, ok) + require.NoError(t, err) + + ok, err = signer2.Verify(vk, msg, signature) + require.True(t, ok) + require.NoError(t, err) } func TestSignRound3RepeatCall(t *testing.T) { @@ -295,7 +299,7 @@ func TestSignRound3BadInput(t *testing.T) { // Actual test: maul the round3Input signer1, _, round3Input = PrepareRound3Input(t) - round3Input[signer1.id].zi = round3Input[signer1.id].zi.Add(testCurve.Scalar.New(2)) + round3Input[signer1.id].Zi = round3Input[signer1.id].Zi.Add(testCurve.Scalar.New(2)) _, err = signer1.SignRound3(round3Input) require.Error(t, err) @@ -307,9 +311,9 @@ func TestSignRound3BadInput(t *testing.T) { } func TestFullRoundsWorks(t *testing.T) { - // Give a full-round test (FROST DKG + FROST Signing) with threshold = 3 and limit = 5, same as the test of tECDSA - threshold := 3 - limit := 5 + // Give a full-round test (FROST DKG + FROST Signing) with threshold = 2 and limit = 3, same as the test of tECDSA + threshold := 2 + limit := 3 // Prepare DKG participants participants := make(map[uint32]*dkg.DkgParticipant, limit) @@ -353,51 +357,46 @@ func TestFullRoundsWorks(t *testing.T) { // Prepare Lagrange coefficients scheme, _ := sharing.NewShamir(uint32(threshold), uint32(limit), testCurve) - lCoeffs, _ := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - participants[1].Id: {Id: participants[1].Id, Value: participants[1].SkShare.Bytes()}, - participants[2].Id: {Id: participants[2].Id, Value: participants[2].SkShare.Bytes()}, - participants[3].Id: {Id: participants[3].Id, Value: participants[3].SkShare.Bytes()}, - }) - - // Using signer 1, 2 and 3 as cosigners - var err error + + // Here we use {1, 3} as 2 of 3 cosigners, we can also set cosigners as {1, 2}, {2, 3} + signerIds := []uint32{1, 3} + lCoeffs, err := scheme.LagrangeCoeffs(signerIds) + require.NoError(t, err) signers := make(map[uint32]*Signer, threshold) - for i := 1; i <= threshold; i++ { - signers[uint32(i)], err = NewSigner(participants[uint32(i)], uint32(i), uint32(threshold), lCoeffs, []uint32{1, 2, 3}, &Ed25519ChallengeDeriver{}) + for _, id := range signerIds { + signers[id], err = NewSigner(participants[id], id, uint32(threshold), lCoeffs, signerIds, &Ed25519ChallengeDeriver{}) require.NoError(t, err) - require.NotNil(t, signers[uint32(i)].skShare) + require.NotNil(t, signers[id].skShare) } // Running sign round 1 round2Input := make(map[uint32]*Round1Bcast, threshold) - for i := 1; i <= threshold; i++ { - round1Out, err := signers[uint32(i)].SignRound1() + for id := range signers { + round1Out, err := signers[id].SignRound1() require.NoError(t, err) - round2Input[signers[uint32(i)].id] = round1Out + round2Input[signers[id].id] = round1Out } // Running sign round 2 msg := []byte("message") round3Input := make(map[uint32]*Round2Bcast, threshold) - for i := 1; i <= threshold; i++ { - round2Out, err := signers[uint32(i)].SignRound2(msg, round2Input) + for id := range signers { + round2Out, err := signers[id].SignRound2(msg, round2Input) require.NoError(t, err) - round3Input[signers[uint32(i)].id] = round2Out + round3Input[signers[id].id] = round2Out } // Running sign round 3 result := make(map[uint32]*Round3Bcast, threshold) - for i := 1; i <= threshold; i++ { - round3Out, err := signers[uint32(i)].SignRound3(round3Input) + for id := range signers { + round3Out, err := signers[id].SignRound3(round3Input) require.NoError(t, err) - result[signers[uint32(i)].id] = round3Out + result[signers[id].id] = round3Out } // Every signer has the same output Schnorr signature - z := result[1].Z - require.Equal(t, z, result[2].Z) - require.Equal(t, z, result[3].Z) - c := result[1].C - require.Equal(t, c, result[2].C) - require.Equal(t, c, result[3].C) + require.Equal(t, result[1].Z, result[3].Z) + // require.Equal(t, z, result[3].Z) + require.Equal(t, result[1].C, result[3].C) + // require.Equal(t, c, result[3].C) } diff --git a/pkg/ted25519/ted25519/ed25519.go b/pkg/ted25519/ted25519/ed25519.go index b527354f..069465f3 100644 --- a/pkg/ted25519/ted25519/ed25519.go +++ b/pkg/ted25519/ted25519/ed25519.go @@ -1,8 +1,6 @@ -// -// Copyright Coinbase, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. // This file implements the Ed25519 signature algorithm. See // https://ed25519.cr.yp.to/. diff --git a/pkg/ted25519/ted25519/ed25519_test.go b/pkg/ted25519/ted25519/ed25519_test.go index 7a908df9..25bac40d 100644 --- a/pkg/ted25519/ted25519/ed25519_test.go +++ b/pkg/ted25519/ted25519/ed25519_test.go @@ -1,8 +1,6 @@ -// -// Copyright Coinbase, Inc. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style diff --git a/pkg/verenc/elgamal/README.md b/pkg/verenc/elgamal/README.md index 9b8d59c0..bfb6ea20 100755 --- a/pkg/verenc/elgamal/README.md +++ b/pkg/verenc/elgamal/README.md @@ -52,7 +52,10 @@ CipherText represents verifiably encrypted ciphertext using El\-Gamal encryption ```go type CipherText struct { - // contains filtered or unexported fields + C1, C2 curves.Point + Nonce []byte + Aead []byte + MsgIsHashed bool } ``` @@ -210,7 +213,7 @@ HomomorphicCipherText represents encrypted ciphertexts that have been added toge ```go type HomomorphicCipherText struct { - // contains filtered or unexported fields + C1, C2 curves.Point } ``` diff --git a/pkg/verenc/elgamal/decryption_key.go b/pkg/verenc/elgamal/decryption_key.go index 82bdeb22..b9959229 100644 --- a/pkg/verenc/elgamal/decryption_key.go +++ b/pkg/verenc/elgamal/decryption_key.go @@ -30,7 +30,7 @@ type DecryptionKey struct { // EncryptionKey returns the corresponding encryption key for this decryption key func (dk DecryptionKey) EncryptionKey() *EncryptionKey { return &EncryptionKey{ - value: dk.x.Point().Generator().Mul(dk.x), + Value: dk.x.Point().Generator().Mul(dk.x), } } @@ -80,7 +80,7 @@ func (dk DecryptionKey) VerifiableDecrypt(cipherText *CipherText) ([]byte, curve if err != nil { return nil, nil, err } - h := dk.EncryptionKey().value.Generator() + h := dk.EncryptionKey().Value.Generator() lhs := h.Mul(msgScalar) if !lhs.Equal(rhs) { return nil, nil, fmt.Errorf("ciphertext mismatch") @@ -100,10 +100,10 @@ func (dk DecryptionKey) VerifiableDecryptWithDomain(domain []byte, cipherText *C return nil, nil, err } ek := dk.EncryptionKey() - genBytes := append(domain, ek.value.ToAffineUncompressed()...) + genBytes := append(domain, ek.Value.ToAffineUncompressed()...) genBytes = append(genBytes, cipherText.Nonce...) - h := ek.value.Hash(genBytes) + h := ek.Value.Hash(genBytes) lhs := h.Mul(msgScalar) if !lhs.Equal(rhs) { return nil, nil, fmt.Errorf("ciphertext mismatch") diff --git a/pkg/verenc/elgamal/encryption_key.go b/pkg/verenc/elgamal/encryption_key.go index 780efd83..301f2c0f 100644 --- a/pkg/verenc/elgamal/encryption_key.go +++ b/pkg/verenc/elgamal/encryption_key.go @@ -45,7 +45,7 @@ type EncryptParams struct { // EncryptionKey encrypts a message to a ciphertext from which // zero-knowledge proofs can be derived type EncryptionKey struct { - value curves.Point + Value curves.Point } // NewKeys creates a new key pair for El-Gamal encryption @@ -67,8 +67,8 @@ func NewKeys(curve *curves.Curve) (*EncryptionKey, *DecryptionKey, error) { // MarshalBinary serializes a key to bytes func (ek EncryptionKey) MarshalBinary() ([]byte, error) { tv := new(encryptionKeyMarshal) - tv.Curve = ek.value.CurveName() - tv.Value = ek.value.ToAffineCompressed() + tv.Curve = ek.Value.CurveName() + tv.Value = ek.Value.ToAffineCompressed() return bare.Marshal(tv) } @@ -87,21 +87,21 @@ func (ek *EncryptionKey) UnmarshalBinary(data []byte) error { if err != nil { return err } - ek.value = value + ek.Value = value return nil } func (ek EncryptionKey) HomomorphicEncrypt(msg curves.Scalar) (*HomomorphicCipherText, error) { - r := ek.value.Scalar().Random(crand.Reader) + r := ek.Value.Scalar().Random(crand.Reader) return &HomomorphicCipherText{ - C1: ek.value.Generator().Mul(r), - C2: ek.value.Mul(r).Add(ek.value.Generator().Mul(msg)), + C1: ek.Value.Generator().Mul(r), + C2: ek.Value.Mul(r).Add(ek.Value.Generator().Mul(msg)), }, nil } func (ek EncryptionKey) encryptWithRandNonce(msg []byte, msgIsHashed bool, r curves.Scalar, h curves.Point, nonce []byte) (*CipherText, error) { // r * Q - t := ek.value.Mul(r) + t := ek.Value.Mul(r) // Derive AEAD encryption key aeadKey, err := core.FiatShamir(new(big.Int).SetBytes(t.ToAffineCompressed())) if err != nil { @@ -117,7 +117,7 @@ func (ek EncryptionKey) encryptWithRandNonce(msg []byte, msgIsHashed bool, r cur } // C1 = r * G - c1 := ek.value.Generator().Mul(r) + c1 := ek.Value.Generator().Mul(r) // C2 = m * H + r * Q msgScalar := r.New(0) if msgIsHashed { diff --git a/pkg/verenc/elgamal/encryption_key_test.go b/pkg/verenc/elgamal/encryption_key_test.go index 3ae7ed2f..fd12cda9 100644 --- a/pkg/verenc/elgamal/encryption_key_test.go +++ b/pkg/verenc/elgamal/encryption_key_test.go @@ -84,5 +84,5 @@ func TestEncryptionKeyMarshaling(t *testing.T) { ekClone := new(EncryptionKey) err = ekClone.UnmarshalBinary(bin) require.NoError(t, err) - require.True(t, ek.value.Equal(ekClone.value)) + require.True(t, ek.Value.Equal(ekClone.Value)) } diff --git a/pkg/verenc/elgamal/proof_enc.go b/pkg/verenc/elgamal/proof_enc.go index 2462c926..09dad5af 100644 --- a/pkg/verenc/elgamal/proof_enc.go +++ b/pkg/verenc/elgamal/proof_enc.go @@ -77,9 +77,9 @@ func (ek EncryptionKey) VerifiableEncrypt(msg []byte, params *EncryptParams) (*C return nil, nil, internal.ErrNilArguments } if params.Blinding == nil { - params.Blinding = ek.value.Scalar().Random(crand.Reader) + params.Blinding = ek.Value.Scalar().Random(crand.Reader) for params.Blinding.IsZero() { - params.Blinding = ek.value.Scalar().Random(crand.Reader) + params.Blinding = ek.Value.Scalar().Random(crand.Reader) } } else if params.Blinding.IsZero() { return nil, nil, internal.ErrZeroValue @@ -92,12 +92,12 @@ func (ek EncryptionKey) VerifiableEncrypt(msg []byte, params *EncryptParams) (*C if params.Domain == nil { // With no domain, the generator is used as h - h = ek.value.Generator() + h = ek.Value.Generator() } else { // If domain is provided, calculate h using domain as part of the input, then encrypt - genBytes := append(params.Domain, ek.value.ToAffineUncompressed()...) + genBytes := append(params.Domain, ek.Value.ToAffineUncompressed()...) genBytes = append(genBytes, cnonce...) - h = ek.value.Hash(genBytes) + h = ek.Value.Hash(genBytes) } cipherText, err = ek.encryptWithRandNonce(msg, params.MessageIsHashed, params.Blinding, h, cnonce) @@ -118,17 +118,17 @@ func (ek EncryptionKey) VerifiableEncrypt(msg []byte, params *EncryptParams) (*C } func (ek EncryptionKey) genProof(nonce, msg []byte, msgIsHashed bool, cipherText *CipherText, blinding curves.Scalar, h curves.Point) (*ProofVerEnc, error) { - r := ek.value.Scalar().Random(crand.Reader) + r := ek.Value.Scalar().Random(crand.Reader) // R1 = r * G - r1 := ek.value.Generator().Mul(r) + r1 := ek.Value.Generator().Mul(r) // R2 = r * Q + b * H - r2 := ek.value.Mul(r).Add(h.Mul(blinding)) + r2 := ek.Value.Mul(r).Add(h.Mul(blinding)) challengeBytes := append(cipherText.C1.ToAffineCompressed(), cipherText.C2.ToAffineCompressed()...) challengeBytes = append(challengeBytes, r1.ToAffineCompressed()...) challengeBytes = append(challengeBytes, r2.ToAffineCompressed()...) challengeBytes = append(challengeBytes, nonce...) - challenge := ek.value.Scalar().Hash(challengeBytes) + challenge := ek.Value.Scalar().Hash(challengeBytes) // b - cm var msgScalar curves.Scalar var err error @@ -161,9 +161,9 @@ func (ek EncryptionKey) VerifyDomainEncryptProof(nonce []byte, ciphertext *Ciphe return internal.ErrNilArguments } - genBytes := append(nonce, ek.value.ToAffineUncompressed()...) + genBytes := append(nonce, ek.Value.ToAffineUncompressed()...) genBytes = append(genBytes, ciphertext.Nonce[:]...) - h := ek.value.Hash(genBytes) + h := ek.Value.Hash(genBytes) return ek.verify(nonce, ciphertext, proof, h) } @@ -181,7 +181,7 @@ func (ek EncryptionKey) VerifyEncryptProof(nonce []byte, ciphertext *CipherText, return internal.ErrNilArguments } - h := ek.value.Generator() + h := ek.Value.Generator() return ek.verify(nonce, ciphertext, proof, h) } @@ -189,13 +189,13 @@ func (ek EncryptionKey) verify(nonce []byte, ciphertext *CipherText, proof *Proo // Reconstruct R1 // R1 = c * C1 + schnorr2 * G = c * ( b * G ) + (r - cb) * G // = (cb + r - cb) * G = r * G - r1 := ciphertext.C1.Mul(proof.challenge).Add(ek.value.Generator().Mul(proof.schnorr2)) + r1 := ciphertext.C1.Mul(proof.challenge).Add(ek.Value.Generator().Mul(proof.schnorr2)) // Reconstruct R2 // R2 = c * C2 + schnorr2 * Q + schnorr1 * H = // c * (b * Q + m * H) + (r - cb) * Q + (b - cm) * H = // (cb + r - cb) * Q + (cm + b - cm) * H = // r * Q + b * H - r2 := ciphertext.C2.Mul(proof.challenge).Add(ek.value.Mul(proof.schnorr2)).Add(h.Mul(proof.schnorr1)) + r2 := ciphertext.C2.Mul(proof.challenge).Add(ek.Value.Mul(proof.schnorr2)).Add(h.Mul(proof.schnorr1)) challengeBytes := append(ciphertext.C1.ToAffineCompressed(), ciphertext.C2.ToAffineCompressed()...) challengeBytes = append(challengeBytes, r1.ToAffineCompressed()...) diff --git a/test/frost_dkg/ed25519/main.go b/test/frost_dkg/ed25519/main.go index 41fd640d..919fdf50 100644 --- a/test/frost_dkg/ed25519/main.go +++ b/test/frost_dkg/ed25519/main.go @@ -80,10 +80,7 @@ func main() { fmt.Printf("Signature verification - %v\n", ok) // Test threshold signing - lCoeffs, err := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - signingShares[1].Id: signingShares[1], - signingShares[2].Id: signingShares[2], - }) + lCoeffs, err := scheme.LagrangeCoeffs([]uint32{signingShares[1].Id, signingShares[2].Id}) if err != nil { panic(err) } diff --git a/test/frost_dkg/frost/main.go b/test/frost_dkg/frost/main.go index a7cb0645..0e1210fa 100644 --- a/test/frost_dkg/frost/main.go +++ b/test/frost_dkg/frost/main.go @@ -58,14 +58,12 @@ func main() { shares[i] = &sharing.ShamirShare{Id: uint32(i + 1), Value: participants[uint32(i+1)].SkShare.Bytes()} } - lCoeffs, _ := scheme.LagrangeCoeffs(map[uint32]*sharing.ShamirShare{ - shares[0].Id: shares[0], - shares[1].Id: shares[1], - shares[2].Id: shares[2], - }) + lCoeffs, err := scheme.LagrangeCoeffs([]uint32{shares[0].Id, shares[1].Id, shares[2].Id}) + if err != nil { + panic(err) + } // Using signer starting from 1 as cosigners - var err error signerIds := make([]uint32, threshold) for i := 0; i < threshold; i++ { signerIds[i] = uint32(i + 1)