From d2b3307ccc608a758f910a4a62a2c1c255a5e03e Mon Sep 17 00:00:00 2001 From: Nicolas Gailly Date: Fri, 12 Jun 2020 17:55:15 +0100 Subject: [PATCH] Mandatory authentication and simplified API (#16) * mandatory authentication and simplified API * renamed signIt to sign * actually renaming the calls... * test of absent auth --- share/dkg/dkg.go | 43 ++++++++++--- share/dkg/dkg_test.go | 55 ++++++++++++---- share/dkg/proto_test.go | 91 ++++++++++++-------------- share/dkg/protocol.go | 137 ++++++++++++---------------------------- share/dkg/structs.go | 22 +++---- 5 files changed, 166 insertions(+), 182 deletions(-) diff --git a/share/dkg/dkg.go b/share/dkg/dkg.go index 7f41e468c..4facb7805 100644 --- a/share/dkg/dkg.go +++ b/share/dkg/dkg.go @@ -11,6 +11,7 @@ import ( "github.com/drand/kyber" "github.com/drand/kyber/encrypt/ecies" "github.com/drand/kyber/share" + "github.com/drand/kyber/sign" "github.com/drand/kyber/util/random" ) @@ -21,7 +22,7 @@ type Suite interface { kyber.Random } -// DkgConfig holds all required information to run a fresh DKG protocol or a +// Config holds all required information to run a fresh DKG protocol or a // resharing protocol. In the case of a new fresh DKG protocol, one must fill // the following fields: Suite, Longterm, NewNodes, Threshold (opt). In the case // of a resharing protocol, one must fill the following: Suite, Longterm, @@ -30,7 +31,7 @@ type Suite interface { // with the current share of the node. If the node using this config is a new // addition and thus has no current share, the PublicCoeffs field be must be // filled in. -type DkgConfig struct { +type Config struct { Suite Suite // Longterm is the longterm secret key. @@ -104,6 +105,10 @@ type DkgConfig struct { // accross runs. A Nonce must be of length 32 bytes. User can get a secure // nonce by calling `GetNonce()`. Nonce []byte + + // Auth is the scheme to use to authentify the packets sent and received + // during the protocol. + Auth sign.Scheme } // Phase is a type that represents the different stages of the DKG protocol. @@ -137,7 +142,7 @@ func (p Phase) String() string { // DistKeyGenerator is the struct that runs the DKG protocol. type DistKeyGenerator struct { // config driving the behavior of DistKeyGenerator - c *DkgConfig + c *Config suite Suite long kyber.Scalar @@ -178,15 +183,18 @@ type DistKeyGenerator struct { olddpub *share.PubPoly } -// NewDistKeyHandler takes a DkgConfig and returns a DistKeyGenerator that is able +// NewDistKeyHandler takes a Config and returns a DistKeyGenerator that is able // to drive the DKG or resharing protocol. -func NewDistKeyHandler(c *DkgConfig) (*DistKeyGenerator, error) { +func NewDistKeyHandler(c *Config) (*DistKeyGenerator, error) { if c.NewNodes == nil && c.OldNodes == nil { return nil, errors.New("dkg: can't run with empty node list") } if len(c.Nonce) != NonceLength { return nil, errors.New("dkg: invalid nonce length") } + if c.Auth == nil { + return nil, errors.New("dkg: need authentication scheme") + } var isResharing bool if c.Share != nil || c.PublicCoeffs != nil { @@ -354,12 +362,15 @@ func (d *DistKeyGenerator) Deals() (*DealBundle, error) { } d.state = DealPhase _, commits := d.dpub.Info() - return &DealBundle{ + bundle := &DealBundle{ DealerIndex: uint32(d.oidx), Deals: deals, Public: commits, SessionID: d.c.Nonce, - }, nil + } + var err error + bundle.Signature, err = d.sign(bundle) + return bundle, err } // ProcessDeals process the deals from all the nodes. Each deal for this node is @@ -508,6 +519,11 @@ func (d *DistKeyGenerator) ProcessDeals(bundles []*DealBundle) (*ResponseBundle, Responses: responses, SessionID: d.c.Nonce, } + sig, err := d.sign(bundle) + if err != nil { + return nil, err + } + bundle.Signature = sig } d.state = ResponsePhase return bundle, nil @@ -621,12 +637,15 @@ func (d *DistKeyGenerator) ProcessResponses(bundles []*ResponseBundle) (*Result, return nil, nil, nil } - var bundle = JustificationBundle{ + var bundle = &JustificationBundle{ DealerIndex: uint32(d.oidx), Justifications: justifications, SessionID: d.c.Nonce, } - return nil, &bundle, nil + + signature, err := d.sign(bundle) + bundle.Signature = signature + return nil, bundle, err } // ProcessJustifications takes the justifications of the nodes and returns the @@ -982,3 +1001,9 @@ func GetNonce() []byte { } return nonce[:] } + +func (d *DistKeyGenerator) sign(p packet) ([]byte, error) { + msg := p.Hash() + priv := d.c.Longterm + return d.c.Auth.Sign(priv, msg) +} diff --git a/share/dkg/dkg_test.go b/share/dkg/dkg_test.go index b84eeccc1..68d9c9f8d 100644 --- a/share/dkg/dkg_test.go +++ b/share/dkg/dkg_test.go @@ -7,6 +7,7 @@ import ( "github.com/drand/kyber/group/edwards25519" "github.com/drand/kyber/pairing/bn256" "github.com/drand/kyber/share" + "github.com/drand/kyber/sign/schnorr" "github.com/drand/kyber/sign/tbls" "github.com/drand/kyber/util/random" clock "github.com/jonboulle/clockwork" @@ -55,7 +56,7 @@ func NodesFromTest(tns []*TestNode) []Node { } // inits the dkg structure -func SetupNodes(nodes []*TestNode, c *DkgConfig) { +func SetupNodes(nodes []*TestNode, c *Config) { nonce := GetNonce() for _, n := range nodes { c2 := *c @@ -69,7 +70,7 @@ func SetupNodes(nodes []*TestNode, c *DkgConfig) { } } -func SetupReshareNodes(nodes []*TestNode, c *DkgConfig, coeffs []kyber.Point) { +func SetupReshareNodes(nodes []*TestNode, c *Config, coeffs []kyber.Point) { nonce := GetNonce() for _, n := range nodes { c2 := *c @@ -140,7 +141,7 @@ type MapDeal func([]*DealBundle) []*DealBundle type MapResponse func([]*ResponseBundle) []*ResponseBundle type MapJustif func([]*JustificationBundle) []*JustificationBundle -func RunDKG(t *testing.T, tns []*TestNode, conf DkgConfig, +func RunDKG(t *testing.T, tns []*TestNode, conf Config, dm MapDeal, rm MapResponse, jm MapJustif) []*Result { SetupNodes(tns, &conf) @@ -203,10 +204,11 @@ func TestDKGFull(t *testing.T) { suite := edwards25519.NewBlakeSHA256Ed25519() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := DkgConfig{ + conf := Config{ Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } results := RunDKG(t, tns, conf, nil, nil, nil) @@ -219,10 +221,11 @@ func TestDKGThreshold(t *testing.T) { suite := edwards25519.NewBlakeSHA256Ed25519() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := DkgConfig{ + conf := Config{ Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } dm := func(deals []*DealBundle) []*DealBundle { @@ -284,10 +287,11 @@ func TestDKGResharing(t *testing.T) { var sigSuite = bn256.NewSuiteG1() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := DkgConfig{ + conf := Config{ Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &conf) @@ -342,12 +346,13 @@ func TestDKGResharing(t *testing.T) { newTns[n-1+i] = NewTestNode(suite, n-1+i) } newList := NodesFromTest(newTns) - newConf := &DkgConfig{ + newConf := &Config{ Suite: suite, NewNodes: newList, OldNodes: list, Threshold: newT, OldThreshold: thr, + Auth: schnorr.NewScheme(suite), } SetupReshareNodes(newTns, newConf, tns[0].res.Key.Commits) @@ -408,11 +413,12 @@ func TestDKGFullFast(t *testing.T) { suite := edwards25519.NewBlakeSHA256Ed25519() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := DkgConfig{ + conf := Config{ FastSync: true, Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } results := RunDKG(t, tns, conf, nil, nil, nil) @@ -425,11 +431,12 @@ func TestDKGNonceInvalid(t *testing.T) { suite := edwards25519.NewBlakeSHA256Ed25519() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := &DkgConfig{ + conf := &Config{ FastSync: true, Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } nonce := GetNonce() conf.Nonce = nonce @@ -445,16 +452,41 @@ func TestDKGNonceInvalid(t *testing.T) { require.Nil(t, dkg) } +func TestDKGAbsentAuth(t *testing.T) { + n := 5 + thr := n + suite := edwards25519.NewBlakeSHA256Ed25519() + tns := GenerateTestNodes(suite, n) + list := NodesFromTest(tns) + conf := &Config{ + FastSync: true, + Suite: suite, + NewNodes: list, + Threshold: thr, + Nonce: GetNonce(), + Longterm: tns[0].Private, + } + dkg, err := NewDistKeyHandler(conf) + require.Error(t, err) + require.Nil(t, dkg) + + conf.Auth = schnorr.NewScheme(suite) + dkg, err = NewDistKeyHandler(conf) + require.NoError(t, err) + require.NotNil(t, dkg) +} + func TestDKGNonceInvalidEviction(t *testing.T) { n := 7 thr := 4 suite := edwards25519.NewBlakeSHA256Ed25519() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := DkgConfig{ + conf := Config{ Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } genPublic := func() []kyber.Point { @@ -516,10 +548,11 @@ func TestDKGInvalidResponse(t *testing.T) { suite := edwards25519.NewBlakeSHA256Ed25519() tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) - conf := DkgConfig{ + conf := Config{ Suite: suite, NewNodes: list, Threshold: thr, + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &conf) diff --git a/share/dkg/proto_test.go b/share/dkg/proto_test.go index ac5ae5549..d0d96b93c 100644 --- a/share/dkg/proto_test.go +++ b/share/dkg/proto_test.go @@ -34,29 +34,29 @@ func (n *TestNetwork) BoardFor(index uint32) *TestBoard { panic("no such indexes") } -func (n *TestNetwork) BroadcastDeal(a AuthDealBundle) { +func (n *TestNetwork) BroadcastDeal(a *DealBundle) { for _, board := range n.boards { - board.newDeals <- a + board.newDeals <- (*a) } } -func (n *TestNetwork) BroadcastResponse(a AuthResponseBundle) { +func (n *TestNetwork) BroadcastResponse(a *ResponseBundle) { for _, board := range n.boards { - board.newResps <- a + board.newResps <- *a } } -func (n *TestNetwork) BroadcastJustification(a AuthJustifBundle) { +func (n *TestNetwork) BroadcastJustification(a *JustificationBundle) { for _, board := range n.boards { - board.newJusts <- a + board.newJusts <- *a } } type TestBoard struct { index uint32 - newDeals chan AuthDealBundle - newResps chan AuthResponseBundle - newJusts chan AuthJustifBundle + newDeals chan DealBundle + newResps chan ResponseBundle + newJusts chan JustificationBundle network *TestNetwork badDeal bool } @@ -65,40 +65,40 @@ func NewTestBoard(index uint32, n int, network *TestNetwork) *TestBoard { return &TestBoard{ network: network, index: index, - newDeals: make(chan AuthDealBundle, n), - newResps: make(chan AuthResponseBundle, n), - newJusts: make(chan AuthJustifBundle, n), + newDeals: make(chan DealBundle, n), + newResps: make(chan ResponseBundle, n), + newJusts: make(chan JustificationBundle, n), } } -func (t *TestBoard) PushDeals(d AuthDealBundle) { +func (t *TestBoard) PushDeals(d *DealBundle) { if t.badDeal { - d.Bundle.Deals[0].EncryptedShare = []byte("bad bad bad") + d.Deals[0].EncryptedShare = []byte("bad bad bad") } t.network.BroadcastDeal(d) } -func (t *TestBoard) PushResponses(r AuthResponseBundle) { +func (t *TestBoard) PushResponses(r *ResponseBundle) { t.network.BroadcastResponse(r) } -func (t *TestBoard) PushJustifications(j AuthJustifBundle) { +func (t *TestBoard) PushJustifications(j *JustificationBundle) { t.network.BroadcastJustification(j) } -func (t *TestBoard) IncomingDeal() <-chan AuthDealBundle { +func (t *TestBoard) IncomingDeal() <-chan DealBundle { return t.newDeals } -func (t *TestBoard) IncomingResponse() <-chan AuthResponseBundle { +func (t *TestBoard) IncomingResponse() <-chan ResponseBundle { return t.newResps } -func (t *TestBoard) IncomingJustification() <-chan AuthJustifBundle { +func (t *TestBoard) IncomingJustification() <-chan JustificationBundle { return t.newJusts } -func SetupProto(tns []*TestNode, dkgC *DkgConfig, protoC *Config, period time.Duration, network *TestNetwork) { +func SetupProto(tns []*TestNode, dkgC *Config, period time.Duration, network *TestNetwork) { for _, n := range tns { clock := clock.NewFakeClock() n.clock = clock @@ -106,8 +106,7 @@ func SetupProto(tns []*TestNode, dkgC *DkgConfig, protoC *Config, period time.Du clock.Sleep(period) }) n.board = network.BoardFor(n.Index) - c2 := *protoC - c2.DkgConfig = *n.dkg.c + c2 := *n.dkg.c proto, err := NewProtocol(&c2, n.board, n.phaser) if err != nil { panic(err) @@ -130,16 +129,14 @@ func TestProtoFull(t *testing.T) { tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) network := NewTestNetwork(n) - dkgConf := DkgConfig{ + dkgConf := Config{ Suite: suite, NewNodes: list, Threshold: thr, - } - protoConf := Config{ - Auth: schnorr.NewScheme(suite), + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &dkgConf) - SetupProto(tns, &dkgConf, &protoConf, period, network) + SetupProto(tns, &dkgConf, period, network) var resCh = make(chan OptionResult, 1) // start all nodes and wait until each end @@ -183,16 +180,14 @@ func TestProtoResharing(t *testing.T) { tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) network := NewTestNetwork(n) - dkgConf := DkgConfig{ + dkgConf := Config{ Suite: suite, NewNodes: list, Threshold: thr, - } - protoConf := Config{ - Auth: schnorr.NewScheme(suite), + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &dkgConf) - SetupProto(tns, &dkgConf, &protoConf, period, network) + SetupProto(tns, &dkgConf, period, network) var resCh = make(chan OptionResult, 1) // start all nodes and wait until each end @@ -244,19 +239,17 @@ func TestProtoResharing(t *testing.T) { newTns[n] = NewTestNode(suite, n) network = NewTestNetwork(newN) newList := NodesFromTest(newTns) - newConf := &DkgConfig{ + newConf := &Config{ Suite: suite, NewNodes: newList, OldNodes: list, Threshold: newT, OldThreshold: thr, - } - newProtoConf := Config{ - Auth: schnorr.NewScheme(suite), + Auth: schnorr.NewScheme(suite), } SetupReshareNodes(newTns, newConf, tns[0].res.Key.Commits) - SetupProto(newTns, newConf, &newProtoConf, period, network) + SetupProto(newTns, newConf, period, network) resCh = make(chan OptionResult, 1) // start all nodes and wait until each end @@ -305,16 +298,14 @@ func TestProtoThreshold(t *testing.T) { list := NodesFromTest(tns) tns = tns[:realN] network := NewTestNetwork(realN) - dkgConf := DkgConfig{ + dkgConf := Config{ Suite: suite, NewNodes: list, Threshold: thr, - } - protoConf := Config{ - Auth: schnorr.NewScheme(suite), + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &dkgConf) - SetupProto(tns, &dkgConf, &protoConf, period, network) + SetupProto(tns, &dkgConf, period, network) var resCh = make(chan OptionResult, 1) // start all nodes and wait until each end @@ -356,17 +347,15 @@ func TestProtoFullFast(t *testing.T) { tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) network := NewTestNetwork(n) - dkgConf := DkgConfig{ + dkgConf := Config{ FastSync: true, Suite: suite, NewNodes: list, Threshold: thr, - } - protoConf := Config{ - Auth: schnorr.NewScheme(suite), + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &dkgConf) - SetupProto(tns, &dkgConf, &protoConf, period, network) + SetupProto(tns, &dkgConf, period, network) var resCh = make(chan OptionResult, 1) // start all nodes and wait until each end @@ -399,17 +388,15 @@ func TestProtoThresholdFast(t *testing.T) { tns := GenerateTestNodes(suite, n) list := NodesFromTest(tns) network := NewTestNetwork(n) - dkgConf := DkgConfig{ + dkgConf := Config{ FastSync: true, Suite: suite, NewNodes: list, Threshold: thr, - } - protoConf := Config{ - Auth: schnorr.NewScheme(suite), + Auth: schnorr.NewScheme(suite), } SetupNodes(tns, &dkgConf) - SetupProto(tns, &dkgConf, &protoConf, period, network) + SetupProto(tns, &dkgConf, period, network) // set a node that will send a bad deal such that all deals are received // "fast", then the normal rounds are happening network.BoardFor(1).badDeal = true diff --git a/share/dkg/protocol.go b/share/dkg/protocol.go index ed2ee1cf1..25d3dfba8 100644 --- a/share/dkg/protocol.go +++ b/share/dkg/protocol.go @@ -8,7 +8,6 @@ import ( "time" "github.com/drand/kyber" - "github.com/drand/kyber/sign" ) // Board is the interface between the dkg protocol and the external world. It @@ -17,12 +16,12 @@ import ( // communication mechanism but one can also use a smart contract based // approach. type Board interface { - PushDeals(AuthDealBundle) - IncomingDeal() <-chan AuthDealBundle - PushResponses(AuthResponseBundle) - IncomingResponse() <-chan AuthResponseBundle - PushJustifications(AuthJustifBundle) - IncomingJustification() <-chan AuthJustifBundle + PushDeals(*DealBundle) + IncomingDeal() <-chan DealBundle + PushResponses(*ResponseBundle) + IncomingResponse() <-chan ResponseBundle + PushJustifications(*JustificationBundle) + IncomingJustification() <-chan JustificationBundle } // Phaser must signal on its channel when the protocol should move to a next @@ -78,22 +77,10 @@ type Protocol struct { board Board phaser Phaser dkg *DistKeyGenerator - conf *Config canIssue bool res chan OptionResult } -// Config is the configuration to give to a Protocol. It currently only embeds -// the dkg config and the authentication scheme. It is meant to be extensible -// and will probably contains more options to log and control the behavior of -// the protocol. -type Config struct { - DkgConfig - // Auth is the scheme to use to verify authentication of the packets - // received from the board. If nil, authentication is not checked. - Auth sign.Scheme -} - // XXX TO DELETE func printNodes(list []Node) string { var arr []string @@ -104,19 +91,18 @@ func printNodes(list []Node) string { } func NewProtocol(c *Config, b Board, phaser Phaser) (*Protocol, error) { - dkg, err := NewDistKeyHandler(&c.DkgConfig) + dkg, err := NewDistKeyHandler(c) if err != nil { return nil, err } // fast sync must only be enabled if there is an authentication scheme - if c.DkgConfig.FastSync && c.Auth == nil { + if c.FastSync && c.Auth == nil { return nil, errors.New("fast sync only allowed with authentication enabled") } p := &Protocol{ board: b, phaser: phaser, dkg: dkg, - conf: c, canIssue: dkg.canIssue, res: make(chan OptionResult, 1), } @@ -125,7 +111,7 @@ func NewProtocol(c *Config, b Board, phaser Phaser) (*Protocol, error) { } func (p *Protocol) Start() { - var fastSync = p.conf.DkgConfig.FastSync + var fastSync = p.dkg.c.FastSync if fastSync { p.startFast() return @@ -154,16 +140,16 @@ func (p *Protocol) Start() { return } case newDeal := <-p.board.IncomingDeal(): - if err := p.VerifySignature(newDeal); err == nil { - deals.Push(newDeal.Bundle) + if err := p.VerifySignature(&newDeal); err == nil { + deals.Push(&newDeal) } case newResp := <-p.board.IncomingResponse(): - if err := p.VerifySignature(newResp); err == nil { - resps.Push(newResp.Bundle) + if err := p.VerifySignature(&newResp); err == nil { + resps.Push(&newResp) } case newJust := <-p.board.IncomingJustification(): - if err := p.VerifySignature(newJust); err == nil { - justifs.Push(newJust.Bundle) + if err := p.VerifySignature(&newJust); err == nil { + justifs.Push(&newJust) } } } @@ -173,8 +159,8 @@ func (p *Protocol) startFast() { var deals = newSet() var resps = newSet() var justifs = newSet() - var newN = len(p.conf.DkgConfig.NewNodes) - var oldN = len(p.conf.DkgConfig.OldNodes) + var newN = len(p.dkg.c.NewNodes) + var oldN = len(p.dkg.c.OldNodes) var phase Phase sendResponseFn := func() bool { if phase != DealPhase { @@ -225,8 +211,8 @@ func (p *Protocol) startFast() { return } case newDeal := <-p.board.IncomingDeal(): - if err := p.VerifySignature(newDeal); err == nil { - deals.Push(newDeal.Bundle) + if err := p.VerifySignature(&newDeal); err == nil { + deals.Push(&newDeal) } // XXX This assumes we receive our own deal bundle since we use a // broadcast channel - may need to revisit that assumption @@ -238,8 +224,8 @@ func (p *Protocol) startFast() { case newResp := <-p.board.IncomingResponse(): // TODO See how can we deal with inconsistent answers from different // share holders - if err := p.VerifySignature(newResp); err == nil { - resps.Push(newResp.Bundle) + if err := p.VerifySignature(&newResp); err == nil { + resps.Push(&newResp) } if resps.Len() == newN { if !sendJustifFn() { @@ -249,8 +235,8 @@ func (p *Protocol) startFast() { case newJust := <-p.board.IncomingJustification(): // TODO see how can we deal with inconsistent answers from different // dealers - if err := p.VerifySignature(newJust); err == nil { - justifs.Push(newJust.Bundle) + if err := p.VerifySignature(&newJust); err == nil { + justifs.Push(&newJust) } if justifs.Len() == oldN { finishFn() @@ -265,7 +251,7 @@ func (p *Protocol) startFast() { // pointer to an AuthDealBundle, AuthResponseBundle, or AuthJustifBundle. // It returns nil if the Auth scheme in the config is nil. func (p *Protocol) VerifySignature(packet interface{}) error { - if p.conf.Auth == nil { + if p.dkg.c.Auth == nil { return nil } var ok bool @@ -273,23 +259,23 @@ func (p *Protocol) VerifySignature(packet interface{}) error { var pub kyber.Point var sig []byte switch auth := packet.(type) { - case AuthDealBundle: - hash = auth.Bundle.Hash() - pub, ok = findIndex(p.conf.DkgConfig.OldNodes, auth.Bundle.DealerIndex) + case *DealBundle: + hash = auth.Hash() + pub, ok = findIndex(p.dkg.c.OldNodes, auth.DealerIndex) if !ok { return errors.New("no nodes with this public key") } sig = auth.Signature - case AuthResponseBundle: - hash = auth.Bundle.Hash() - pub, ok = findIndex(p.conf.DkgConfig.NewNodes, auth.Bundle.ShareIndex) + case *ResponseBundle: + hash = auth.Hash() + pub, ok = findIndex(p.dkg.c.NewNodes, auth.ShareIndex) if !ok { return errors.New("no nodes with this public key") } sig = auth.Signature - case AuthJustifBundle: - hash = auth.Bundle.Hash() - pub, ok = findIndex(p.conf.DkgConfig.OldNodes, auth.Bundle.DealerIndex) + case *JustificationBundle: + hash = auth.Hash() + pub, ok = findIndex(p.dkg.c.OldNodes, auth.DealerIndex) if !ok { return errors.New("no nodes with this public key") } @@ -298,20 +284,10 @@ func (p *Protocol) VerifySignature(packet interface{}) error { return errors.New("unknown packet type") } - err := p.conf.Auth.Verify(pub, hash, sig) + err := p.dkg.c.Auth.Verify(pub, hash, sig) return err } -type hashable interface { - Hash() []byte -} - -func (p *Protocol) signIt(h hashable) ([]byte, error) { - msg := h.Hash() - priv := p.conf.Longterm - return p.conf.Auth.Sign(priv, msg) -} - func (p *Protocol) sendDeals() bool { if !p.canIssue { return true @@ -323,22 +299,14 @@ func (p *Protocol) sendDeals() bool { } return false } - authBundle := AuthDealBundle{ - Bundle: bundle, - } - if p.conf.Auth != nil { - sig, err := p.signIt(bundle) - if err != nil { - return false - } - authBundle.Signature = sig + if bundle != nil { + p.board.PushDeals(bundle) } - p.board.PushDeals(authBundle) return true } func (p *Protocol) sendResponses(deals []*DealBundle) bool { - resp, err := p.dkg.ProcessDeals(deals) + bundle, err := p.dkg.ProcessDeals(deals) if err != nil { p.res <- OptionResult{ Error: err, @@ -346,18 +314,8 @@ func (p *Protocol) sendResponses(deals []*DealBundle) bool { // we signal the end since we can't go on return false } - if resp != nil { - authBundle := AuthResponseBundle{ - Bundle: resp, - } - if p.conf.Auth != nil { - sig, err := p.signIt(resp) - if err != nil { - return false - } - authBundle.Signature = sig - } - p.board.PushResponses(authBundle) + if bundle != nil { + p.board.PushResponses(bundle) } return true } @@ -378,17 +336,7 @@ func (p *Protocol) sendJustifications(resps []*ResponseBundle) bool { return false } if just != nil { - authBundle := AuthJustifBundle{ - Bundle: just, - } - if p.conf.Auth != nil { - sig, err := p.signIt(just) - if err != nil { - return false - } - authBundle.Signature = sig - } - p.board.PushJustifications(authBundle) + p.board.PushJustifications(just) } return true } @@ -410,11 +358,6 @@ type OptionResult struct { Error error } -type packet interface { - Hash() []byte - Index() Index -} - type set struct { vals map[Index]packet bad []Index diff --git a/share/dkg/structs.go b/share/dkg/structs.go index 56c199e58..84649d28b 100644 --- a/share/dkg/structs.go +++ b/share/dkg/structs.go @@ -105,6 +105,8 @@ type DealBundle struct { Public []kyber.Point // SessionID of the current run SessionID []byte + // Signature over the hash of the whole bundle + Signature []byte } // Hash hashes the index, public coefficients and deals @@ -149,6 +151,8 @@ type ResponseBundle struct { Responses []Response // SessionID of the current run SessionID []byte + // Signature over the hash of the whole bundle + Signature []byte } // Hash hashes the share index and responses @@ -194,6 +198,8 @@ type JustificationBundle struct { Justifications []Justification // SessionID of the current run SessionID []byte + // Signature over the hash of the whole bundle + Signature []byte } type Justification struct { @@ -221,17 +227,7 @@ func (j *JustificationBundle) Index() Index { return j.DealerIndex } -type AuthDealBundle struct { - Bundle *DealBundle - Signature []byte -} - -type AuthResponseBundle struct { - Bundle *ResponseBundle - Signature []byte -} - -type AuthJustifBundle struct { - Bundle *JustificationBundle - Signature []byte +type packet interface { + Hash() []byte + Index() Index }