aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMission Liao <mission.liao@dexon.org>2018-09-26 16:55:15 +0800
committerGitHub <noreply@github.com>2018-09-26 16:55:15 +0800
commit663817d3e0d5a3c28cb0c5e378a533e242af5fdf (patch)
tree8d1952cc04a5735ce7cd060445667160bb21fc60 /crypto
parente8468d7206dbee2a8dfb34bfccc29d0d7273a777 (diff)
downloaddexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.tar
dexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.tar.gz
dexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.tar.bz2
dexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.tar.lz
dexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.tar.xz
dexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.tar.zst
dexon-consensus-663817d3e0d5a3c28cb0c5e378a533e242af5fdf.zip
core: move crypto to core/crypto (#140)
- Move key-holder to authenticator Make core.keyHolder public as core.Authenticator, it is not required to make this part an interface. - Make private when there is no need to go public. - Fix data race
Diffstat (limited to 'crypto')
-rw-r--r--crypto/dkg/constant.go26
-rw-r--r--crypto/dkg/dkg.go381
-rw-r--r--crypto/dkg/dkg_test.go461
-rw-r--r--crypto/dkg/utils.go69
-rw-r--r--crypto/eth/eth.go120
-rw-r--r--crypto/eth/eth_test.go93
-rw-r--r--crypto/interfaces.go45
-rw-r--r--crypto/utils.go41
-rw-r--r--crypto/utils_test.go52
9 files changed, 0 insertions, 1288 deletions
diff --git a/crypto/dkg/constant.go b/crypto/dkg/constant.go
deleted file mode 100644
index 119613b..0000000
--- a/crypto/dkg/constant.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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 dkg
-
-import (
- "github.com/Spiderpowa/bls/ffi/go/bls"
-)
-
-const (
- curve = bls.CurveFp382_2
-)
diff --git a/crypto/dkg/dkg.go b/crypto/dkg/dkg.go
deleted file mode 100644
index f2a2f3a..0000000
--- a/crypto/dkg/dkg.go
+++ /dev/null
@@ -1,381 +0,0 @@
-// 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 dkg
-
-import (
- "encoding/json"
- "fmt"
-
- "github.com/Spiderpowa/bls/ffi/go/bls"
-
- "github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
-)
-
-var (
- // ErrDuplicatedShare is reported when adding an private key share of same id.
- ErrDuplicatedShare = fmt.Errorf("invalid share")
- // ErrNoIDToRecover is reported when no id is provided for recovering private
- // key.
- ErrNoIDToRecover = fmt.Errorf("no id to recover private key")
- // ErrShareNotFound is reported when the private key share of id is not found
- // when recovering private key.
- ErrShareNotFound = fmt.Errorf("share not found")
-)
-
-var publicKeyLength int
-
-func init() {
- bls.Init(curve)
-
- pubKey := &bls.PublicKey{}
- publicKeyLength = len(pubKey.Serialize())
-}
-
-// PrivateKey represents a private key structure implments
-// Crypto.PrivateKey interface.
-type PrivateKey struct {
- privateKey bls.SecretKey
- publicKey PublicKey
-}
-
-// MarshalJSON implements json.Marshaller.
-func (prv *PrivateKey) MarshalJSON() ([]byte, error) {
- return json.Marshal(&prv.privateKey)
-}
-
-// UnmarshalJSON implements json.Unmarshaller.
-func (prv *PrivateKey) UnmarshalJSON(data []byte) error {
- return json.Unmarshal(data, &prv.privateKey)
-}
-
-// ID is the id for DKG protocol.
-type ID = bls.ID
-
-// IDs is an array of ID.
-type IDs []ID
-
-// PublicKey represents a public key structure implements
-// Crypto.PublicKey interface.
-type PublicKey struct {
- publicKey bls.PublicKey
-}
-
-// PrivateKeyShares represents a private key shares for DKG protocol.
-type PrivateKeyShares struct {
- shares []PrivateKey
- shareIndex map[ID]int
- masterPrivateKey []bls.SecretKey
-}
-
-// PublicKeyShares represents a public key shares for DKG protocol.
-type PublicKeyShares struct {
- shares []PublicKey
- shareIndex map[ID]int
- masterPublicKey []bls.PublicKey
-}
-
-// MarshalJSON implements json.Marshaller.
-func (pubs *PublicKeyShares) MarshalJSON() ([]byte, error) {
- type Alias PublicKeyShares
- data := &struct {
- MasterPublicKeys []*bls.PublicKey `json:"master_public_keys"`
- }{
- make([]*bls.PublicKey, len(pubs.masterPublicKey)),
- }
- for i := range pubs.masterPublicKey {
- data.MasterPublicKeys[i] = &pubs.masterPublicKey[i]
- }
- return json.Marshal(data)
-}
-
-// UnmarshalJSON implements json.Unmarshaller.
-func (pubs *PublicKeyShares) UnmarshalJSON(data []byte) error {
- type Alias PublicKeyShares
- aux := &struct {
- MasterPublicKeys []*bls.PublicKey `json:"master_public_keys"`
- }{}
- if err := json.Unmarshal(data, &aux); err != nil {
- return err
- }
- mpk := make([]bls.PublicKey, len(aux.MasterPublicKeys))
- for i, pk := range aux.MasterPublicKeys {
- mpk[i] = *pk
- }
- pubs.masterPublicKey = mpk
- return nil
-}
-
-// NewID creates a ew ID structure.
-func NewID(id []byte) ID {
- var blsID bls.ID
- blsID.SetLittleEndian(id)
- return blsID
-}
-
-// NewPrivateKey creates a new PrivateKey structure.
-func NewPrivateKey() *PrivateKey {
- var key bls.SecretKey
- key.SetByCSPRNG()
- return &PrivateKey{
- privateKey: key,
- publicKey: *newPublicKey(&key),
- }
-}
-
-// NewPrivateKeyShares creates a DKG private key shares of threshold t.
-func NewPrivateKeyShares(t int) (*PrivateKeyShares, *PublicKeyShares) {
- var prv bls.SecretKey
- prv.SetByCSPRNG()
- msk := prv.GetMasterSecretKey(t)
- mpk := bls.GetMasterPublicKey(msk)
- return &PrivateKeyShares{
- masterPrivateKey: msk,
- shareIndex: make(map[ID]int),
- }, &PublicKeyShares{
- shareIndex: make(map[ID]int),
- masterPublicKey: mpk,
- }
-}
-
-// NewEmptyPrivateKeyShares creates an empty private key shares.
-func NewEmptyPrivateKeyShares() *PrivateKeyShares {
- return &PrivateKeyShares{
- shareIndex: make(map[ID]int),
- }
-}
-
-// SetParticipants sets the DKG participants.
-func (prvs *PrivateKeyShares) SetParticipants(IDs IDs) {
- prvs.shares = make([]PrivateKey, len(IDs))
- prvs.shareIndex = make(map[ID]int, len(IDs))
- for idx, ID := range IDs {
- prvs.shares[idx].privateKey.Set(prvs.masterPrivateKey, &ID)
- prvs.shareIndex[ID] = idx
- }
-}
-
-// AddShare adds a share.
-func (prvs *PrivateKeyShares) AddShare(ID ID, share *PrivateKey) error {
- if idx, exist := prvs.shareIndex[ID]; exist {
- if !share.privateKey.IsEqual(&prvs.shares[idx].privateKey) {
- return ErrDuplicatedShare
- }
- return nil
- }
- prvs.shareIndex[ID] = len(prvs.shares)
- prvs.shares = append(prvs.shares, *share)
- return nil
-}
-
-// RecoverPrivateKey recovers private key from the shares.
-func (prvs *PrivateKeyShares) RecoverPrivateKey(qualifyIDs IDs) (
- *PrivateKey, error) {
- var prv PrivateKey
- if len(qualifyIDs) == 0 {
- return nil, ErrNoIDToRecover
- }
- for i, ID := range qualifyIDs {
- idx, exist := prvs.shareIndex[ID]
- if !exist {
- return nil, ErrShareNotFound
- }
- if i == 0 {
- prv.privateKey = prvs.shares[idx].privateKey
- continue
- }
- prv.privateKey.Add(&prvs.shares[idx].privateKey)
- }
- return &prv, nil
-}
-
-// RecoverPublicKey recovers public key from the shares.
-func (prvs *PrivateKeyShares) RecoverPublicKey(qualifyIDs IDs) (
- *PublicKey, error) {
- var pub PublicKey
- if len(qualifyIDs) == 0 {
- return nil, ErrNoIDToRecover
- }
- for i, ID := range qualifyIDs {
- idx, exist := prvs.shareIndex[ID]
- if !exist {
- return nil, ErrShareNotFound
- }
- if i == 0 {
- pub.publicKey = *prvs.shares[idx].privateKey.GetPublicKey()
- continue
- }
- pub.publicKey.Add(prvs.shares[idx].privateKey.GetPublicKey())
- }
- return &pub, nil
-}
-
-// Share returns the share for the ID.
-func (prvs *PrivateKeyShares) Share(ID ID) (*PrivateKey, bool) {
- idx, exist := prvs.shareIndex[ID]
- if !exist {
- return nil, false
- }
- return &prvs.shares[idx], true
-}
-
-// NewEmptyPublicKeyShares creates an empty public key shares.
-func NewEmptyPublicKeyShares() *PublicKeyShares {
- return &PublicKeyShares{
- shareIndex: make(map[ID]int),
- }
-}
-
-// Share returns the share for the ID.
-func (pubs *PublicKeyShares) Share(ID ID) (*PublicKey, error) {
- idx, exist := pubs.shareIndex[ID]
- if exist {
- return &pubs.shares[idx], nil
- }
- var pk PublicKey
- if err := pk.publicKey.Set(pubs.masterPublicKey, &ID); err != nil {
- return nil, err
- }
- pubs.AddShare(ID, &pk)
- return &pk, nil
-}
-
-// AddShare adds a share.
-func (pubs *PublicKeyShares) AddShare(ID ID, share *PublicKey) error {
- if idx, exist := pubs.shareIndex[ID]; exist {
- if !share.publicKey.IsEqual(&pubs.shares[idx].publicKey) {
- return ErrDuplicatedShare
- }
- return nil
- }
- pubs.shareIndex[ID] = len(pubs.shares)
- pubs.shares = append(pubs.shares, *share)
- return nil
-}
-
-// VerifyPrvShare verifies if the private key shares is valid.
-func (pubs *PublicKeyShares) VerifyPrvShare(ID ID, share *PrivateKey) (
- bool, error) {
- var pk bls.PublicKey
- if err := pk.Set(pubs.masterPublicKey, &ID); err != nil {
- return false, err
- }
- return pk.IsEqual(share.privateKey.GetPublicKey()), nil
-}
-
-// VerifyPubShare verifies if the public key shares is valid.
-func (pubs *PublicKeyShares) VerifyPubShare(ID ID, share *PublicKey) (
- bool, error) {
- var pk bls.PublicKey
- if err := pk.Set(pubs.masterPublicKey, &ID); err != nil {
- return false, err
- }
- return pk.IsEqual(&share.publicKey), nil
-}
-
-// RecoverPublicKey recovers private key from the shares.
-func (pubs *PublicKeyShares) RecoverPublicKey(qualifyIDs IDs) (
- *PublicKey, error) {
- var pub PublicKey
- if len(qualifyIDs) == 0 {
- return nil, ErrNoIDToRecover
- }
- for i, ID := range qualifyIDs {
- idx, exist := pubs.shareIndex[ID]
- if !exist {
- return nil, ErrShareNotFound
- }
- if i == 0 {
- pub.publicKey = pubs.shares[idx].publicKey
- continue
- }
- pub.publicKey.Add(&pubs.shares[idx].publicKey)
- }
- return &pub, nil
-}
-
-// MasterKeyBytes returns []byte representation of master public key.
-func (pubs *PublicKeyShares) MasterKeyBytes() []byte {
- bytes := make([]byte, 0, len(pubs.masterPublicKey)*publicKeyLength)
- for _, pk := range pubs.masterPublicKey {
- bytes = append(bytes, pk.Serialize()...)
- }
- return bytes
-}
-
-// newPublicKey creates a new PublicKey structure.
-func newPublicKey(prvKey *bls.SecretKey) *PublicKey {
- return &PublicKey{
- publicKey: *prvKey.GetPublicKey(),
- }
-}
-
-// PublicKey returns the public key associate this private key.
-func (prv *PrivateKey) PublicKey() crypto.PublicKey {
- return prv.publicKey
-}
-
-// Sign calculates a signature.
-func (prv *PrivateKey) Sign(hash common.Hash) (crypto.Signature, error) {
- msg := string(hash[:])
- sign := prv.privateKey.Sign(msg)
- return crypto.Signature(sign.Serialize()), nil
-}
-
-// Bytes returns []byte representation of private key.
-func (prv *PrivateKey) Bytes() []byte {
- return prv.privateKey.GetLittleEndian()
-}
-
-// SetBytes sets the private key data to []byte.
-func (prv *PrivateKey) SetBytes(bytes []byte) error {
- var key bls.SecretKey
- if err := key.SetLittleEndian(bytes); err != nil {
- return err
- }
- prv.privateKey = key
- prv.publicKey = *newPublicKey(&prv.privateKey)
- return nil
-}
-
-// String returns string representation of privat key.
-func (prv *PrivateKey) String() string {
- return prv.privateKey.GetHexString()
-}
-
-// VerifySignature checks that the given public key created signature over hash.
-func (pub PublicKey) VerifySignature(
- hash common.Hash, signature crypto.Signature) bool {
- if len(signature) == 0 {
- return false
- }
- var sig bls.Sign
- if err := sig.Deserialize(signature[:]); err != nil {
- fmt.Println(err)
- return false
- }
- msg := string(hash[:])
- return sig.Verify(&pub.publicKey, msg)
-}
-
-// Bytes returns []byte representation of public key.
-func (pub PublicKey) Bytes() []byte {
- var bytes []byte
- pub.publicKey.Deserialize(bytes)
- return bytes
-}
diff --git a/crypto/dkg/dkg_test.go b/crypto/dkg/dkg_test.go
deleted file mode 100644
index badb0ce..0000000
--- a/crypto/dkg/dkg_test.go
+++ /dev/null
@@ -1,461 +0,0 @@
-// 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 dkg
-
-import (
- "encoding/binary"
- "math/rand"
- "sort"
- "sync"
- "testing"
-
- "github.com/stretchr/testify/suite"
-
- "github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
-)
-
-type DKGTestSuite struct {
- suite.Suite
-}
-
-type member struct {
- id ID
- prvShares *PrivateKeyShares
- pubShares *PublicKeyShares
- receivedPrvShares *PrivateKeyShares
- receivedPubShares map[ID]*PublicKeyShares
-}
-
-func (s *DKGTestSuite) genID(k int) IDs {
- IDs := make(IDs, 0, k)
- for i := 0; i < k; i++ {
- id := make([]byte, 8)
- binary.LittleEndian.PutUint64(id, rand.Uint64())
- IDs = append(IDs, NewID(id))
- }
- return IDs
-}
-
-func (s *DKGTestSuite) sendKey(senders []member, receivers []member) {
- receiveFrom := make(map[ID][]member)
- for _, sender := range senders {
- for _, receiver := range receivers {
- // Here's the demonstration of DKG protocol. `pubShares` is broadcasted
- // and all the receiver would save it to the `receivedPubShares`.
- // Do not optimize the memory usage of this part.
- receiver.receivedPubShares[sender.id] = sender.pubShares
- prvShare, ok := sender.prvShares.Share(receiver.id)
- s.Require().True(ok)
- pubShare, err := sender.pubShares.Share(receiver.id)
- s.Require().NoError(err)
- valid, err := receiver.receivedPubShares[sender.id].
- VerifyPrvShare(receiver.id, prvShare)
- s.Require().NoError(err)
- s.Require().True(valid)
- valid, err = receiver.receivedPubShares[sender.id].
- VerifyPubShare(receiver.id, pubShare)
- s.Require().NoError(err)
- s.Require().True(valid)
- receiveFrom[receiver.id] = append(receiveFrom[receiver.id], sender)
- }
- }
- // The received order do not need to be the same.
- for _, receiver := range receivers {
- rand.Shuffle(len(senders), func(i, j int) {
- receiveFrom[receiver.id][i], receiveFrom[receiver.id][j] =
- receiveFrom[receiver.id][j], receiveFrom[receiver.id][i]
- })
- for _, sender := range receiveFrom[receiver.id] {
- prvShare, ok := sender.prvShares.Share(receiver.id)
- s.Require().True(ok)
- err := receiver.receivedPrvShares.AddShare(sender.id, prvShare)
- s.Require().NoError(err)
- }
- }
-}
-
-func (s *DKGTestSuite) signWithQualifyIDs(
- member member, qualifyIDs IDs, hash common.Hash) PartialSignature {
- prvKey, err := member.receivedPrvShares.RecoverPrivateKey(qualifyIDs)
- s.Require().NoError(err)
- sig, err := prvKey.Sign(hash)
- s.Require().NoError(err)
- return PartialSignature(sig)
-}
-
-func (s *DKGTestSuite) verifySigWithQualifyIDs(
- members []member, qualifyIDs IDs,
- signer ID, hash common.Hash, sig PartialSignature) bool {
- membersIdx := make(map[ID]int)
- for idx, member := range members {
- membersIdx[member.id] = idx
- }
- pubShares := NewEmptyPublicKeyShares()
- for _, id := range qualifyIDs {
- idx, exist := membersIdx[id]
- s.Require().True(exist)
- member := members[idx]
- pubShare, err := member.pubShares.Share(signer)
- s.Require().NoError(err)
- err = pubShares.AddShare(id, pubShare)
- s.Require().NoError(err)
- }
- pubKey, err := pubShares.RecoverPublicKey(qualifyIDs)
- s.Require().NoError(err)
- return pubKey.VerifySignature(hash, crypto.Signature(sig))
-}
-
-func (s *DKGTestSuite) TestVerifyKeyShares() {
- invalidID := NewID([]byte{0})
- ids := []ID{NewID([]byte{1}), NewID([]byte{2}), NewID([]byte{3})}
- members := []member{}
- for _, id := range ids {
- members = append(members, member{
- id: id,
- receivedPubShares: make(map[ID]*PublicKeyShares),
- })
- }
-
- prvShares, pubShares := NewPrivateKeyShares(2)
- prvShares.SetParticipants(ids)
-
- _, ok := prvShares.Share(invalidID)
- s.False(ok)
- for _, id := range ids {
- prvShare, ok := prvShares.Share(id)
- s.Require().True(ok)
- valid, err := pubShares.VerifyPrvShare(id, prvShare)
- s.Require().NoError(err)
- s.True(valid)
- pubShare, err := pubShares.Share(id)
- s.Require().NoError(err)
- valid, err = pubShares.VerifyPubShare(id, pubShare)
- s.Require().NoError(err)
- s.True(valid)
- }
-
- // Test of faulty private/public key.
- invalidPrvShare := NewPrivateKey()
- valid, err := pubShares.VerifyPrvShare(ids[0], invalidPrvShare)
- s.Require().NoError(err)
- s.False(valid)
-
- invalidPubShare, ok := invalidPrvShare.PublicKey().(PublicKey)
- s.Require().True(ok)
- valid, err = pubShares.VerifyPubShare(ids[0], &invalidPubShare)
- s.Require().NoError(err)
- s.False(valid)
-
- // Test of faulty signature.
- for idx := range members {
- members[idx].prvShares, members[idx].pubShares = NewPrivateKeyShares(2)
- members[idx].prvShares.SetParticipants(ids)
- members[idx].receivedPrvShares = NewEmptyPrivateKeyShares()
- }
- s.sendKey(members, members)
- hash := crypto.Keccak256Hash([]byte("πŸ‘ΎπŸ‘ΎπŸ‘ΎπŸ‘ΎπŸ‘ΎπŸ‘Ύ"))
- sig, err := invalidPrvShare.Sign(hash)
- s.Require().NoError(err)
- psig := PartialSignature(sig)
- for _, member := range members {
- valid = s.verifySigWithQualifyIDs(members, ids, member.id, hash, psig)
- s.False(valid)
- }
-
- // Test of faulty group signature.
- groupPubShares := make([]*PublicKeyShares, 0, len(members))
- sigs := make([]PartialSignature, 0, len(members))
- for _, member := range members {
- sigs = append(sigs, s.signWithQualifyIDs(member, ids, hash))
- groupPubShares = append(groupPubShares, member.pubShares)
- }
- sigs[0] = psig
- recoverSig, err := RecoverSignature(sigs, ids)
- s.Require().NoError(err)
-
- pubKey := RecoverGroupPublicKey(groupPubShares)
- s.False(pubKey.VerifySignature(hash, recoverSig))
-}
-
-func (s *DKGTestSuite) TestDKGProtocol() {
- k := 5
- members := []member{}
- ids := s.genID((k + 1) * 2)
- for _, id := range ids {
- members = append(members, member{
- id: id,
- receivedPubShares: make(map[ID]*PublicKeyShares),
- })
- }
-
- for idx := range members {
- members[idx].prvShares, members[idx].pubShares = NewPrivateKeyShares(k)
- members[idx].prvShares.SetParticipants(ids)
- members[idx].receivedPrvShares = NewEmptyPrivateKeyShares()
- }
- // Randomly select non-disqualified members.
- nums := make([]int, len(members))
- for i := range nums {
- nums[i] = i
- }
- rand.Shuffle(len(nums), func(i, j int) {
- nums[i], nums[j] = nums[j], nums[i]
- })
- nums = nums[:rand.Intn(len(members))]
- sort.Ints(nums)
- qualify := make([]member, 0, len(nums))
- for _, idx := range nums {
- qualify = append(qualify, members[idx])
- }
- // TODO(jimmy-dexon): Remove below line after finishing test of random select.
- qualify = members
- // Members are partitioned into two groups.
- grp1, grp2 := members[:k+1], members[k+1:]
- collectIDs := func(members []member) IDs {
- IDs := make(IDs, 0, len(members))
- for _, member := range members {
- IDs = append(IDs, member.id)
- }
- return IDs
- }
- signMsg := func(
- members []member, qualify []member, hash common.Hash) []PartialSignature {
- ids := collectIDs(qualify)
- sigs := make([]PartialSignature, 0, len(members))
- for _, member := range members {
- sig := s.signWithQualifyIDs(member, ids, hash)
- sigs = append(sigs, sig)
- }
- return sigs
- }
- verifySig := func(
- members []member,
- signer []ID, sig []PartialSignature, qualify []member, hash common.Hash) bool {
- ids := collectIDs(qualify)
- for i := range sig {
- if !s.verifySigWithQualifyIDs(members, ids, signer[i], hash, sig[i]) {
- return false
- }
- }
- return true
- }
- s.sendKey(qualify, grp1)
- s.sendKey(qualify, grp2)
- hash := crypto.Keccak256Hash([]byte("πŸ›«"))
- sig1 := signMsg(grp1, qualify, hash)
- sig2 := signMsg(grp2, qualify, hash)
- s.True(verifySig(members, collectIDs(grp1), sig1, qualify, hash))
- s.True(verifySig(members, collectIDs(grp2), sig2, qualify, hash))
- recoverSig1, err := RecoverSignature(sig1, collectIDs(grp1))
- s.Require().NoError(err)
- recoverSig2, err := RecoverSignature(sig2, collectIDs(grp2))
- s.Require().NoError(err)
- s.Equal(recoverSig1, recoverSig2)
-
- pubShares := make([]*PublicKeyShares, 0, len(members))
- for _, member := range members {
- pubShares = append(pubShares, member.pubShares)
- }
- groupPK := RecoverGroupPublicKey(pubShares)
- s.True(groupPK.VerifySignature(hash, recoverSig1))
- s.True(groupPK.VerifySignature(hash, recoverSig2))
-}
-
-func (s *DKGTestSuite) TestSignature() {
- prvKey := NewPrivateKey()
- pubKey := prvKey.PublicKey()
- hash := crypto.Keccak256Hash([]byte("πŸ›«"))
- sig, err := prvKey.Sign(hash)
- s.Require().NoError(err)
- s.True(pubKey.VerifySignature(hash, sig))
- sig[0]++
- s.False(pubKey.VerifySignature(hash, sig))
- sig = crypto.Signature{}
- s.False(pubKey.VerifySignature(hash, sig))
-}
-
-func TestDKG(t *testing.T) {
- suite.Run(t, new(DKGTestSuite))
-}
-
-func BenchmarkDKGProtocol(b *testing.B) {
- t := 33
- n := 100
- s := new(DKGTestSuite)
-
- self := member{}
- members := make([]*member, n-1)
- ids := make(IDs, n)
-
- b.Run("DKG", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- self.id = s.genID(1)[0]
- self.receivedPubShares = make(map[ID]*PublicKeyShares, n)
- for idx, id := range s.genID(n - 1) {
- ids[idx] = id
- }
- for idx := range members {
- members[idx] = &member{
- id: ids[idx],
- receivedPubShares: make(map[ID]*PublicKeyShares),
- receivedPrvShares: NewEmptyPrivateKeyShares(),
- }
- }
- ids[n-1] = self.id
- prvShares := make(map[ID]*PrivateKey, n)
- for idx := range members {
- members[idx].prvShares, members[idx].pubShares = NewPrivateKeyShares(t)
- members[idx].prvShares.SetParticipants(ids)
- prvShare, ok := members[idx].prvShares.Share(self.id)
- if !ok {
- b.FailNow()
- }
- prvShares[members[idx].id] = prvShare
- }
-
- b.StartTimer()
- self.prvShares, self.pubShares = NewPrivateKeyShares(t)
- self.prvShares.SetParticipants(ids)
- self.receivedPrvShares = NewEmptyPrivateKeyShares()
- for _, member := range members {
- self.receivedPubShares[member.id] = member.pubShares
- }
- self.receivedPubShares[self.id] = self.pubShares
- prvShare, ok := self.prvShares.Share(self.id)
- if !ok {
- b.FailNow()
- }
- prvShares[self.id] = prvShare
- for id, prvShare := range prvShares {
- ok, err := self.receivedPubShares[id].VerifyPrvShare(self.id, prvShare)
- if err != nil {
- b.Fatalf("%v", err)
- }
- if !ok {
- b.FailNow()
- }
- if err := self.receivedPrvShares.AddShare(id, prvShare); err != nil {
- b.Fatalf("%v", err)
- }
- }
- if _, err := self.receivedPrvShares.RecoverPrivateKey(ids); err != nil {
- b.Fatalf("%v", err)
- }
- }
- })
-
- hash := crypto.Keccak256Hash([]byte("πŸ–"))
- b.Run("Share-Sign", func(b *testing.B) {
- for i := 0; i < b.N; i++ {
- b.StopTimer()
- prvKey, err := self.receivedPrvShares.RecoverPrivateKey(ids)
- if err != nil {
- b.Fatalf("%v", err)
- }
- b.StartTimer()
- if _, err := prvKey.Sign(hash); err != nil {
- b.Fatalf("%v", err)
- }
- }
- })
-
- sendKey := func(sender *member, receiver *member, b *testing.B) {
- receiver.receivedPubShares[sender.id] = sender.pubShares
- prvShare, ok := sender.prvShares.Share(receiver.id)
- if !ok {
- b.FailNow()
- }
- ok, err := receiver.receivedPubShares[sender.id].VerifyPrvShare(
- receiver.id, prvShare)
- if err != nil {
- b.Fatalf("%v", err)
- }
- if !ok {
- b.FailNow()
- }
- if err := receiver.receivedPrvShares.AddShare(sender.id, prvShare); err != nil {
- b.Fatalf("%v", err)
- }
- }
-
- members = append(members, &self)
-
- for _, sender := range members {
- wg := sync.WaitGroup{}
- for _, receiver := range members {
- if sender == receiver {
- continue
- }
- wg.Add(1)
- go func(receiver *member) {
- sendKey(sender, receiver, b)
- wg.Done()
- }(receiver)
- }
- wg.Wait()
- }
- wg := sync.WaitGroup{}
- for _, m := range members {
- wg.Add(1)
- go func(member *member) {
- sendKey(member, member, b)
- wg.Done()
- }(m)
- }
- wg.Wait()
-
- sign := func(member *member) PartialSignature {
- prvKey, err := member.receivedPrvShares.RecoverPrivateKey(ids)
- if err != nil {
- b.Fatalf("%v", err)
- }
- sig, err := prvKey.Sign(hash)
- if err != nil {
- b.Fatalf("%v", err)
- }
- return PartialSignature(sig)
- }
-
- b.Run("Combine-Sign", func(b *testing.B) {
- b.StopTimer()
- sigs := make([]PartialSignature, n)
- for idx, member := range members {
- sigs[idx] = sign(member)
- }
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- if _, err := RecoverSignature(sigs, ids); err != nil {
- b.Fatalf("%v", err)
- }
- }
- })
-
- b.Run("Recover-GroupPK", func(b *testing.B) {
- b.StopTimer()
- pubShares := make([]*PublicKeyShares, 0, len(members))
- for _, member := range members {
- pubShares = append(pubShares, member.pubShares)
- }
- b.StartTimer()
- for i := 0; i < b.N; i++ {
- RecoverGroupPublicKey(pubShares)
- }
- })
-}
diff --git a/crypto/dkg/utils.go b/crypto/dkg/utils.go
deleted file mode 100644
index 3684964..0000000
--- a/crypto/dkg/utils.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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 dkg
-
-import (
- "fmt"
-
- "github.com/Spiderpowa/bls/ffi/go/bls"
-
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
-)
-
-// PartialSignature is a partial signature in DKG+TSIG protocol.
-type PartialSignature crypto.Signature
-
-var (
- // ErrEmptySignature is reported if the signature is empty.
- ErrEmptySignature = fmt.Errorf("invalid empty signature")
-)
-
-// RecoverSignature recovers TSIG signature.
-func RecoverSignature(sigs []PartialSignature, signerIDs IDs) (
- crypto.Signature, error) {
- blsSigs := make([]bls.Sign, len(sigs))
- for i, sig := range sigs {
- if len(sig) == 0 {
- return nil, ErrEmptySignature
- }
- if err := blsSigs[i].Deserialize([]byte(sig)); err != nil {
- return nil, err
- }
- }
- var recoverSig bls.Sign
- if err := recoverSig.Recover(blsSigs, []bls.ID(signerIDs)); err != nil {
- return nil, err
- }
- return crypto.Signature(recoverSig.Serialize()), nil
-}
-
-// RecoverGroupPublicKey recovers group public key.
-func RecoverGroupPublicKey(pubShares []*PublicKeyShares) *PublicKey {
- var pub *PublicKey
- for _, pubShare := range pubShares {
- pk0 := pubShare.masterPublicKey[0]
- if pub == nil {
- pub = &PublicKey{
- publicKey: pk0,
- }
- } else {
- pub.publicKey.Add(&pk0)
- }
- }
- return pub
-}
diff --git a/crypto/eth/eth.go b/crypto/eth/eth.go
deleted file mode 100644
index c3c5a7c..0000000
--- a/crypto/eth/eth.go
+++ /dev/null
@@ -1,120 +0,0 @@
-// 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 eth
-
-import (
- "crypto/ecdsa"
-
- ethcrypto "github.com/ethereum/go-ethereum/crypto"
-
- "github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
-)
-
-// PrivateKey represents a private key structure used in geth and implments
-// Crypto.PrivateKey interface.
-type PrivateKey struct {
- privateKey ecdsa.PrivateKey
- publicKey PublicKey
-}
-
-// PublicKey represents a public key structure used in geth and implements
-// Crypto.PublicKey interface.
-type PublicKey struct {
- publicKey []byte
-}
-
-// NewPrivateKey creates a new PrivateKey structure.
-func NewPrivateKey() (*PrivateKey, error) {
- key, err := ethcrypto.GenerateKey()
- if err != nil {
- return nil, err
- }
- return &PrivateKey{
- privateKey: *key,
- publicKey: *newPublicKey(key),
- }, nil
-}
-
-// newPublicKey creates a new PublicKey structure.
-func newPublicKey(prvKey *ecdsa.PrivateKey) *PublicKey {
- return &PublicKey{
- publicKey: ethcrypto.CompressPubkey(&prvKey.PublicKey),
- }
-}
-
-// DecompressPubkey parses a public key in the 33-byte compressed format.
-func DecompressPubkey(pubkey []byte) (PublicKey, error) {
- _, err := ethcrypto.DecompressPubkey(pubkey)
- return PublicKey{
- publicKey: pubkey,
- }, err
-}
-
-// PublicKey returns the public key associate this private key.
-func (prv *PrivateKey) PublicKey() crypto.PublicKey {
- return prv.publicKey
-}
-
-// Sign calculates an ECDSA signature.
-//
-// This function is susceptible to chosen plaintext attacks that can leak
-// information about the private key that is used for signing. Callers must
-// be aware that the given hash cannot be chosen by an adversery. Common
-// solution is to hash any input before calculating the signature.
-//
-// The produced signature is in the [R || S || V] format where V is 0 or 1.
-func (prv *PrivateKey) Sign(hash common.Hash) (
- sig crypto.Signature, err error) {
- s, err := ethcrypto.Sign(hash[:], &prv.privateKey)
- sig = crypto.Signature(s)
- return
-}
-
-// VerifySignature checks that the given public key created signature over hash.
-// The public key should be in compressed (33 bytes) or uncompressed (65 bytes)
-// format.
-// The signature should have the 64 byte [R || S] format.
-func (pub PublicKey) VerifySignature(
- hash common.Hash, signature crypto.Signature) bool {
- if len(signature) == 65 {
- // The last byte is for ecrecover.
- signature = signature[:64]
- }
- return ethcrypto.VerifySignature(pub.publicKey, hash[:], signature)
-}
-
-// Compress encodes a public key to the 33-byte compressed format.
-func (pub PublicKey) Compress() []byte {
- return pub.publicKey
-}
-
-// Bytes returns the []byte representation of public key.
-func (pub PublicKey) Bytes() []byte {
- return pub.Compress()
-}
-
-// SigToPub returns the PublicKey that created the given signature.
-func SigToPub(
- hash common.Hash, signature crypto.Signature) (crypto.PublicKey, error) {
- key, err := ethcrypto.SigToPub(hash[:], signature[:])
- if err != nil {
- return PublicKey{}, err
- }
- return PublicKey{publicKey: ethcrypto.CompressPubkey(key)}, nil
-}
diff --git a/crypto/eth/eth_test.go b/crypto/eth/eth_test.go
deleted file mode 100644
index f6f48cb..0000000
--- a/crypto/eth/eth_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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 eth
-
-import (
- "testing"
-
- "github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/stretchr/testify/suite"
-)
-
-type ETHCryptoTestSuite struct {
- suite.Suite
-}
-
-func (s *ETHCryptoTestSuite) TestSignature() {
- prv1, err := NewPrivateKey()
- s.Require().Nil(err)
- hash1 := common.NewRandomHash()
- hash2 := common.NewRandomHash()
-
- // Test that same private key should produce same signature.
- sig11, err := prv1.Sign(hash1)
- s.Require().Nil(err)
- sig112, err := prv1.Sign(hash1)
- s.Require().Nil(err)
- s.Equal(sig11, sig112)
-
- // Test that different private key should produce different signature.
- prv2, err := NewPrivateKey()
- s.Require().Nil(err)
- sig21, err := prv2.Sign(hash1)
- s.Require().Nil(err)
- s.NotEqual(sig11, sig21)
-
- // Test that different hash should produce different signature.
- sig12, err := prv1.Sign(hash2)
- s.Require().Nil(err)
- s.NotEqual(sig11, sig12)
-
- // Test VerifySignature with correct public key.
- pub1, ok := prv1.PublicKey().(PublicKey)
- s.Require().True(ok)
- s.True(pub1.VerifySignature(hash1, sig11))
-
- // Test VerifySignature with wrong hash.
- s.False(pub1.VerifySignature(hash2, sig11))
- // Test VerifySignature with wrong signature.
- s.False(pub1.VerifySignature(hash1, sig21))
- // Test VerifySignature with wrong public key.
- pub2 := prv2.PublicKey()
- s.False(pub2.VerifySignature(hash1, sig11))
-
- // Test compress and decompress of public key.
- compressPub1 := pub1.Compress()
- decompressPub1, err := DecompressPubkey(compressPub1)
- s.Require().Nil(err)
- s.Equal(pub1, decompressPub1)
- s.True(decompressPub1.VerifySignature(hash1, sig11))
-}
-
-func (s *ETHCryptoTestSuite) TestSigToPub() {
- prv, err := NewPrivateKey()
- s.Require().Nil(err)
- data := "DEXON is infinitely scalable and low-latency."
- hash := crypto.Keccak256Hash([]byte(data))
- sigmsg, err := prv.Sign(hash)
- s.Require().Nil(err)
-
- pubkey, err := SigToPub(hash, sigmsg)
- s.Require().Nil(err)
- s.Equal(pubkey, prv.PublicKey())
-}
-
-func TestCrypto(t *testing.T) {
- suite.Run(t, new(ETHCryptoTestSuite))
-}
diff --git a/crypto/interfaces.go b/crypto/interfaces.go
deleted file mode 100644
index 280082e..0000000
--- a/crypto/interfaces.go
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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 crypto
-
-import (
- "github.com/dexon-foundation/dexon-consensus-core/common"
-)
-
-// Signature is the basic signature type in DEXON.
-type Signature []byte
-
-// PrivateKey describes the asymmetric cryptography interface that interacts
-// with the private key.
-type PrivateKey interface {
- // PublicKey returns the public key associate this private key.
- PublicKey() PublicKey
-
- // Sign calculates a signature.
- Sign(hash common.Hash) (sig Signature, err error)
-}
-
-// PublicKey describes the asymmetric cryptography interface that interacts
-// with the public key.
-type PublicKey interface {
- // VerifySignature checks that the given public key created signature over hash.
- VerifySignature(hash common.Hash, signature Signature) bool
-
- // Bytes returns the []byte representation of public key.
- Bytes() []byte
-}
diff --git a/crypto/utils.go b/crypto/utils.go
deleted file mode 100644
index 07a8b2b..0000000
--- a/crypto/utils.go
+++ /dev/null
@@ -1,41 +0,0 @@
-// 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 crypto
-
-import (
- "encoding/hex"
-
- "github.com/ethereum/go-ethereum/crypto"
-
- "github.com/dexon-foundation/dexon-consensus-core/common"
-)
-
-// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
-// converting it to an internal Hash data structure.
-func Keccak256Hash(data ...[]byte) (h common.Hash) {
- return common.Hash(crypto.Keccak256Hash(data...))
-}
-
-// Clone returns a deep copy of a signature.
-func (sig Signature) Clone() Signature {
- return append(Signature{}, sig...)
-}
-
-func (sig Signature) String() string {
- return hex.EncodeToString([]byte(sig[:]))
-}
diff --git a/crypto/utils_test.go b/crypto/utils_test.go
deleted file mode 100644
index 977027a..0000000
--- a/crypto/utils_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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 crypto
-
-import (
- "encoding/hex"
- "testing"
-
- "github.com/stretchr/testify/suite"
-)
-
-type CryptoTestSuite struct {
- suite.Suite
-}
-
-func (s *CryptoTestSuite) TestHash() {
- cases := []struct {
- input string
- output string
- }{
- {"DEXON ROCKS!",
- "1a3f3a424aaa464e51b693585bba3a0c439d5f1ad3b5868e46d9f830225983bd"},
- {"Dexon Foundation",
- "25ed4237aa978bfe706cc11c7a46a95de1a46302faea7ff6e900b03fa2b7b480"},
- {"INFINITELY SCALABLE AND LOW-LATENCY",
- "ed3384c58a434fbc0bc887a85659eddf997e7da978ab66565ac865f995b77cf1"},
- }
- for _, testcase := range cases {
- hash := Keccak256Hash([]byte(testcase.input))
- output := hex.EncodeToString(hash[:])
- s.Equal(testcase.output, output)
- }
-}
-
-func TestCrypto(t *testing.T) {
- suite.Run(t, new(CryptoTestSuite))
-}