diff options
author | Mission Liao <mission.liao@dexon.org> | 2018-09-25 11:02:32 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-25 11:02:32 +0800 |
commit | 01a6b236b82391adfedad1498f3497a70d4cf948 (patch) | |
tree | 54807a80c7756d62ca1ff8c860cdb43c870c90a6 /core | |
parent | dc6b4d947aa017aa37e51178f52d9dccb47864ae (diff) | |
download | tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.tar tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.tar.gz tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.tar.bz2 tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.tar.lz tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.tar.xz tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.tar.zst tangerine-consensus-01a6b236b82391adfedad1498f3497a70d4cf948.zip |
core: add key holder (#130)
The purpose to add this module is to export
the functionality to sign/verify data without
exporting private key directly.
Diffstat (limited to 'core')
-rw-r--r-- | core/interfaces.go | 26 | ||||
-rw-r--r-- | core/key-holder.go | 98 | ||||
-rw-r--r-- | core/key-holder_test.go | 96 |
3 files changed, 220 insertions, 0 deletions
diff --git a/core/interfaces.go b/core/interfaces.go index 36b0160..5e1002c 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -108,3 +108,29 @@ type Ticker interface { // Stop the ticker. Stop() } + +// Signer defines a role to sign data. +type Signer interface { + // SignBlock signs a block. + SignBlock(b *types.Block) error + // SignVote signs a vote. + SignVote(v *types.Vote) error + // SignCRS sign a block's CRS signature. + SignCRS(b *types.Block, crs common.Hash) error +} + +// CryptoVerifier defines a role to verify data in crypto's way. +type CryptoVerifier interface { + // VerifyBlock verifies if a block is properly signed or not. + VerifyBlock(b *types.Block) (ok bool, err error) + // VerifyVote verfies if a vote is properly signed or not. + VerifyVote(v *types.Vote) (ok bool, err error) + // VerifyCRS verifies if a CRS signature of one block is valid or not. + VerifyCRS(b *types.Block, crs common.Hash) (ok bool, err error) +} + +// Authenticator verify/sign who own the data. +type Authenticator interface { + Signer + CryptoVerifier +} diff --git a/core/key-holder.go b/core/key-holder.go new file mode 100644 index 0000000..355c823 --- /dev/null +++ b/core/key-holder.go @@ -0,0 +1,98 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus-core library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus-core library. If not, see +// <http://www.gnu.org/licenses/>. + +package core + +import ( + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" + "github.com/dexon-foundation/dexon-consensus-core/crypto" +) + +type keyHolder struct { + prvKey crypto.PrivateKey + pubKey crypto.PublicKey + sigToPub SigToPubFn +} + +func newKeyHolder(prvKey crypto.PrivateKey, sigToPub SigToPubFn) *keyHolder { + return &keyHolder{ + prvKey: prvKey, + pubKey: prvKey.PublicKey(), + sigToPub: sigToPub, + } +} + +// SignBlock implements core.Signer. +func (h *keyHolder) SignBlock(b *types.Block) (err error) { + b.ProposerID = types.NewNodeID(h.pubKey) + if b.Hash, err = hashBlock(b); err != nil { + return + } + if b.Signature, err = h.prvKey.Sign(b.Hash); err != nil { + return + } + return +} + +// SignVote implements core.Signer. +func (h *keyHolder) SignVote(v *types.Vote) (err error) { + v.ProposerID = types.NewNodeID(h.pubKey) + v.Signature, err = h.prvKey.Sign(hashVote(v)) + return +} + +// SignCRS implements core.Signer +func (h *keyHolder) SignCRS(b *types.Block, crs common.Hash) (err error) { + if b.ProposerID != types.NewNodeID(h.pubKey) { + err = ErrInvalidProposerID + return + } + b.CRSSignature, err = h.prvKey.Sign(hashCRS(b, crs)) + return +} + +// VerifyBlock implements core.CryptoVerifier. +func (h *keyHolder) VerifyBlock(b *types.Block) (err error) { + hash, err := hashBlock(b) + if err != nil { + return + } + if hash != b.Hash { + err = ErrIncorrectHash + return + } + pubKey, err := h.sigToPub(b.Hash, b.Signature) + if err != nil { + return + } + if !b.ProposerID.Equal(crypto.Keccak256Hash(pubKey.Bytes())) { + err = ErrIncorrectSignature + return + } + return +} + +// VerifyVote implements core.CryptoVerifier. +func (h *keyHolder) VerifyVote(v *types.Vote) (bool, error) { + return verifyVoteSignature(v, h.sigToPub) +} + +// VerifyWitness implements core.CryptoVerifier. +func (h *keyHolder) VerifyCRS(b *types.Block, crs common.Hash) (bool, error) { + return verifyCRSSignature(b, crs, h.sigToPub) +} diff --git a/core/key-holder_test.go b/core/key-holder_test.go new file mode 100644 index 0000000..cb5fda7 --- /dev/null +++ b/core/key-holder_test.go @@ -0,0 +1,96 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus-core library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus-core library. If not, see +// <http://www.gnu.org/licenses/>. + +package core + +import ( + "testing" + "time" + + "github.com/dexon-foundation/dexon-consensus-core/common" + "github.com/dexon-foundation/dexon-consensus-core/core/types" + "github.com/dexon-foundation/dexon-consensus-core/crypto/eth" + "github.com/stretchr/testify/suite" +) + +type KeyHolderTestSuite struct { + suite.Suite +} + +func (s *KeyHolderTestSuite) setupKeyHolder() *keyHolder { + k, err := eth.NewPrivateKey() + s.NoError(err) + return newKeyHolder(k, eth.SigToPub) +} + +func (s *KeyHolderTestSuite) TestBlock() { + k := s.setupKeyHolder() + b := &types.Block{ + ParentHash: common.NewRandomHash(), + Position: types.Position{ + ShardID: 1, + ChainID: 2, + Height: 3, + }, + Timestamp: time.Now().UTC(), + } + s.NoError(k.SignBlock(b)) + s.NoError(k.VerifyBlock(b)) +} + +func (s *KeyHolderTestSuite) TestVote() { + k := s.setupKeyHolder() + v := &types.Vote{ + ProposerID: types.NodeID{Hash: common.NewRandomHash()}, + Type: types.VoteConfirm, + BlockHash: common.NewRandomHash(), + Period: 123, + Position: types.Position{ + ShardID: 2, + ChainID: 4, + Height: 6, + }} + s.NoError(k.SignVote(v)) + ok, err := k.VerifyVote(v) + s.True(ok) + s.NoError(err) +} + +func (s *KeyHolderTestSuite) TestCRS() { + k := s.setupKeyHolder() + b := &types.Block{ + ParentHash: common.NewRandomHash(), + Position: types.Position{ + ShardID: 7, + ChainID: 8, + Height: 9, + }, + Timestamp: time.Now().UTC(), + } + crs := common.NewRandomHash() + s.Error(k.SignCRS(b, crs)) + // Hash block before hash CRS. + s.NoError(k.SignBlock(b)) + s.NoError(k.SignCRS(b, crs)) + ok, err := k.VerifyCRS(b, crs) + s.True(ok) + s.NoError(err) +} + +func TestKeyHolder(t *testing.T) { + suite.Run(t, new(KeyHolderTestSuite)) +} |