// // Copyright Coinbase, Inc. All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // // Package gennaro is an implementation of the DKG part of https://eprint.iacr.org/2020/540.pdf package gennaro import ( "crypto/elliptic" "fmt" "source.quilibrium.com/quilibrium/monorepo/nekryptology/internal" "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/core/curves" v1 "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/sharing/v1" ) // Participant is a DKG player that contains information needed to perform DKG rounds // and yield a secret key share and public key when finished type Participant struct { round int curve elliptic.Curve scalar curves.EcScalar otherParticipantShares map[uint32]*dkgParticipantData id uint32 skShare *curves.Element verificationKey *v1.ShareVerifier feldman *v1.Feldman pedersen *v1.Pedersen pedersenResult *v1.PedersenResult } // NewParticipant creates a participant ready to perform a DKG // `id` is the integer value identifier for this participant // `threshold` is the minimum bound for the secret sharing scheme // `generator` is the blinding factor generator used by pedersen's verifiable secret sharing // `otherParticipants` is the integer value identifiers for the other participants // `id` and `otherParticipants` must be the set of integers 1,2,....,n func NewParticipant(id, threshold uint32, generator *curves.EcPoint, scalar curves.EcScalar, otherParticipants ...uint32) (*Participant, error) { if generator == nil || len(otherParticipants) == 0 { return nil, internal.ErrNilArguments } err := validIds(append(otherParticipants, id)) if err != nil { return nil, err } limit := uint32(len(otherParticipants)) + 1 feldman, err := v1.NewFeldman(threshold, limit, generator.Curve) if err != nil { return nil, err } pedersen, err := v1.NewPedersen(threshold, limit, generator) if err != nil { return nil, err } otherParticipantShares := make(map[uint32]*dkgParticipantData, len(otherParticipants)) for _, id := range otherParticipants { otherParticipantShares[id] = &dkgParticipantData{ Id: id, } } return &Participant{ id: id, round: 1, curve: generator.Curve, scalar: scalar, feldman: feldman, pedersen: pedersen, otherParticipantShares: otherParticipantShares, }, nil } // Determines if the SSIDs are exactly the values 1..n. func validIds(ids []uint32) error { // Index idMap := make(map[uint32]bool, len(ids)) for _, id := range ids { idMap[id] = true } // Check for i := 1; i <= len(ids); i++ { if ok := idMap[uint32(i)]; !ok { return fmt.Errorf("the ID list %v is invalid. Values must be 1,2,..,n.", ids) } } return nil } type dkgParticipantData struct { Id uint32 Share *v1.ShamirShare Verifiers []*v1.ShareVerifier }