Merge pull request #370 from harmony-one/rj_branch

Say goodbye to Schnorr sig and kyber package and mark BLS done
pull/371/head
Rongjian Lan 6 years ago committed by GitHub
commit 5e3b354e43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .gitmodules
  2. 6
      api/proto/bcconn/bcconn_test.go
  3. 6
      consensus/README.md
  4. 1
      consensus/consensus.go
  5. 4
      consensus/consensus_leader_msg_test.go
  6. 12
      consensus/consensus_leader_test.go
  7. 10
      consensus/consensus_test.go
  8. 24
      consensus/consensus_validator_test.go
  9. 6
      crypto/bls/bls_test.go
  10. 440
      crypto/cosi.go
  11. 6
      crypto/curve.go
  12. 40
      crypto/pki/utils.go
  13. 35
      crypto/pki/utils_test.go
  14. 10
      crypto/suite.go
  15. 4
      internal/newnode/newnode.go
  16. 15
      internal/utils/utils.go
  17. 7
      internal/utils/utils_test.go
  18. 6
      node/node_handler_test.go
  19. 8
      node/node_test.go
  20. 1
      vendor/github.com/dedis/kyber

3
.gitmodules vendored

@ -5,6 +5,3 @@
[submodule "vendor/github.com/golang/protobuf"] [submodule "vendor/github.com/golang/protobuf"]
path = vendor/github.com/golang/protobuf path = vendor/github.com/golang/protobuf
url = https://github.com/golang/protobuf url = https://github.com/golang/protobuf
[submodule "vendor/github.com/dedis/kyber"]
path = vendor/github.com/dedis/kyber
url = https://github.com/dedis/kyber

@ -13,7 +13,7 @@ func TestSerializeDeserializeNodeInfo(t *testing.T) {
var ip, port string var ip, port string
ip = "127.0.0.1" ip = "127.0.0.1"
port = "8080" port = "8080"
_, pk := utils.GenKeyBLS(ip, port) _, pk := utils.GenKey(ip, port)
pkb := pk.Serialize() pkb := pk.Serialize()
nodeInfo := &node.Info{IP: ip, Port: port, PubKey: pkb} nodeInfo := &node.Info{IP: ip, Port: port, PubKey: pkb}
serializedNI := SerializeNodeInfo(nodeInfo) serializedNI := SerializeNodeInfo(nodeInfo)
@ -29,13 +29,13 @@ func TestSerializeDeserializeRandomInfo(t *testing.T) {
ip = "127.0.0.1" ip = "127.0.0.1"
port = "8080" port = "8080"
_, pk := utils.GenKeyBLS(ip, port) _, pk := utils.GenKey(ip, port)
pkb := pk.Serialize() pkb := pk.Serialize()
nodeInfo1 := &node.Info{IP: ip, Port: port, PubKey: pkb} nodeInfo1 := &node.Info{IP: ip, Port: port, PubKey: pkb}
ip = "127.0.0.1" ip = "127.0.0.1"
port = "9080" port = "9080"
_, pk2 := utils.GenKeyBLS(ip, port) _, pk2 := utils.GenKey(ip, port)
pkb2 := pk2.Serialize() pkb2 := pk2.Serialize()
nodeInfo2 := &node.Info{IP: ip, Port: port, PubKey: pkb2} nodeInfo2 := &node.Info{IP: ip, Port: port, PubKey: pkb2}

@ -1,5 +1 @@
Consensus package includes the Harmony BFT consensus protocol code. Consensus package includes the Harmony BFT consensus protocol code, which uses BLS-based multi-signature to cosign the new block. The details are in Harmony's new [consensus protocol design](https://talk.harmony.one/t/bls-based-practical-bft-consensus/131).
For now, the current implementation is still in experimental phase because it's coded using the two-round Schnorr-based multi-signature similar to [Byzcoin's design](https://www.usenix.org/system/files/conference/usenixsecurity16/sec16_paper_kokoris-kogias.pdf).
We will migrate to BLS-based multi-signature following Harmony's new [consensus protocol design](https://talk.harmony.one/t/bls-based-practical-bft-consensus/131).

@ -449,7 +449,6 @@ func (consensus *Consensus) DebugPrintValidators() {
// UpdatePublicKeys updates the PublicKeys variable, protected by a mutex // UpdatePublicKeys updates the PublicKeys variable, protected by a mutex
func (consensus *Consensus) UpdatePublicKeys(pubKeys []*bls.PublicKey) int { func (consensus *Consensus) UpdatePublicKeys(pubKeys []*bls.PublicKey) int {
consensus.pubKeyLock.Lock() consensus.pubKeyLock.Lock()
// consensus.PublicKeys = make([]kyber.Point, len(pubKeys))
consensus.PublicKeys = append(pubKeys[:0:0], pubKeys...) consensus.PublicKeys = append(pubKeys[:0:0], pubKeys...)
consensus.pubKeyLock.Unlock() consensus.pubKeyLock.Unlock()

@ -29,10 +29,10 @@ func TestConstructAnnounceMessage(test *testing.T) {
func TestConstructPreparedMessage(test *testing.T) { func TestConstructPreparedMessage(test *testing.T) {
leaderPriKey, leaderPubKey := utils.GenKeyBLS("127.0.0.1", "6000") leaderPriKey, leaderPubKey := utils.GenKey("127.0.0.1", "6000")
leader := p2p.Peer{IP: "127.0.0.1", Port: "6000", PubKey: leaderPubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "6000", PubKey: leaderPubKey}
validatorPriKey, validatorPubKey := utils.GenKeyBLS("127.0.0.1", "5555") validatorPriKey, validatorPubKey := utils.GenKey("127.0.0.1", "5555")
validator := p2p.Peer{IP: "127.0.0.1", Port: "5555", PubKey: validatorPubKey} validator := p2p.Peer{IP: "127.0.0.1", Port: "5555", PubKey: validatorPubKey}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
host, err := p2pimpl.NewHost(&leader, priKey) host, err := p2pimpl.NewHost(&leader, priKey)

@ -33,7 +33,7 @@ func TestProcessMessageLeaderPrepare(test *testing.T) {
defer ctrl.Finish() defer ctrl.Finish()
leader := p2p.Peer{IP: ip, Port: "7777"} leader := p2p.Peer{IP: ip, Port: "7777"}
_, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) _, leader.PubKey = utils.GenKey(leader.IP, leader.Port)
validators := make([]p2p.Peer, 3) validators := make([]p2p.Peer, 3)
hosts := make([]p2p.Host, 3) hosts := make([]p2p.Host, 3)
@ -41,7 +41,7 @@ func TestProcessMessageLeaderPrepare(test *testing.T) {
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
port := fmt.Sprintf("%d", 7788+i) port := fmt.Sprintf("%d", 7788+i)
validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1} validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1}
_, validators[i].PubKey = utils.GenKeyBLS(validators[i].IP, validators[i].Port) _, validators[i].PubKey = utils.GenKey(validators[i].IP, validators[i].Port)
} }
m := mock_host.NewMockHost(ctrl) m := mock_host.NewMockHost(ctrl)
@ -78,7 +78,7 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) {
defer ctrl.Finish() defer ctrl.Finish()
leader := p2p.Peer{IP: ip, Port: "7777"} leader := p2p.Peer{IP: ip, Port: "7777"}
_, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) _, leader.PubKey = utils.GenKey(leader.IP, leader.Port)
validators := make([]p2p.Peer, 3) validators := make([]p2p.Peer, 3)
hosts := make([]p2p.Host, 3) hosts := make([]p2p.Host, 3)
@ -86,7 +86,7 @@ func TestProcessMessageLeaderPrepareInvalidSignature(test *testing.T) {
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
port := fmt.Sprintf("%d", 7788+i) port := fmt.Sprintf("%d", 7788+i)
validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1} validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1}
_, validators[i].PubKey = utils.GenKeyBLS(validators[i].IP, validators[i].Port) _, validators[i].PubKey = utils.GenKey(validators[i].IP, validators[i].Port)
} }
m := mock_host.NewMockHost(ctrl) m := mock_host.NewMockHost(ctrl)
@ -129,7 +129,7 @@ func TestProcessMessageLeaderCommit(test *testing.T) {
defer ctrl.Finish() defer ctrl.Finish()
leader := p2p.Peer{IP: ip, Port: "8889"} leader := p2p.Peer{IP: ip, Port: "8889"}
_, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) _, leader.PubKey = utils.GenKey(leader.IP, leader.Port)
validators := make([]p2p.Peer, 3) validators := make([]p2p.Peer, 3)
hosts := make([]p2p.Host, 3) hosts := make([]p2p.Host, 3)
@ -137,7 +137,7 @@ func TestProcessMessageLeaderCommit(test *testing.T) {
for i := 0; i < 3; i++ { for i := 0; i < 3; i++ {
port := fmt.Sprintf("%d", 8788+i) port := fmt.Sprintf("%d", 8788+i)
validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1} validators[i] = p2p.Peer{IP: ip, Port: port, ValidatorID: i + 1}
_, validators[i].PubKey = utils.GenKeyBLS(validators[i].IP, validators[i].Port) _, validators[i].PubKey = utils.GenKey(validators[i].IP, validators[i].Port)
} }
m := mock_host.NewMockHost(ctrl) m := mock_host.NewMockHost(ctrl)

@ -37,11 +37,11 @@ func TestNew(test *testing.T) {
} }
func TestRemovePeers(t *testing.T) { func TestRemovePeers(t *testing.T) {
_, pk1 := utils.GenKeyBLS("1", "1") _, pk1 := utils.GenKey("1", "1")
_, pk2 := utils.GenKeyBLS("2", "2") _, pk2 := utils.GenKey("2", "2")
_, pk3 := utils.GenKeyBLS("3", "3") _, pk3 := utils.GenKey("3", "3")
_, pk4 := utils.GenKeyBLS("4", "4") _, pk4 := utils.GenKey("4", "4")
_, pk5 := utils.GenKeyBLS("5", "5") _, pk5 := utils.GenKey("5", "5")
p1 := p2p.Peer{IP: "127.0.0.1", Port: "19901", PubKey: pk1} p1 := p2p.Peer{IP: "127.0.0.1", Port: "19901", PubKey: pk1}
p2 := p2p.Peer{IP: "127.0.0.1", Port: "19902", PubKey: pk2} p2 := p2p.Peer{IP: "127.0.0.1", Port: "19902", PubKey: pk2}

@ -23,14 +23,14 @@ func TestProcessMessageValidatorAnnounce(test *testing.T) {
defer ctrl.Finish() defer ctrl.Finish()
leader := p2p.Peer{IP: "127.0.0.1", Port: "9982"} leader := p2p.Peer{IP: "127.0.0.1", Port: "9982"}
_, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) _, leader.PubKey = utils.GenKey(leader.IP, leader.Port)
validator1 := p2p.Peer{IP: "127.0.0.1", Port: "9984", ValidatorID: 1} validator1 := p2p.Peer{IP: "127.0.0.1", Port: "9984", ValidatorID: 1}
_, validator1.PubKey = utils.GenKeyBLS(validator1.IP, validator1.Port) _, validator1.PubKey = utils.GenKey(validator1.IP, validator1.Port)
validator2 := p2p.Peer{IP: "127.0.0.1", Port: "9986", ValidatorID: 2} validator2 := p2p.Peer{IP: "127.0.0.1", Port: "9986", ValidatorID: 2}
_, validator2.PubKey = utils.GenKeyBLS(validator2.IP, validator2.Port) _, validator2.PubKey = utils.GenKey(validator2.IP, validator2.Port)
validator3 := p2p.Peer{IP: "127.0.0.1", Port: "9988", ValidatorID: 3} validator3 := p2p.Peer{IP: "127.0.0.1", Port: "9988", ValidatorID: 3}
_, validator3.PubKey = utils.GenKeyBLS(validator3.IP, validator3.Port) _, validator3.PubKey = utils.GenKey(validator3.IP, validator3.Port)
m := mock_host.NewMockHost(ctrl) m := mock_host.NewMockHost(ctrl)
// Asserts that the first and only call to Bar() is passed 99. // Asserts that the first and only call to Bar() is passed 99.
@ -77,14 +77,14 @@ func TestProcessMessageValidatorPrepared(test *testing.T) {
defer ctrl.Finish() defer ctrl.Finish()
leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"} leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"}
_, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) _, leader.PubKey = utils.GenKey(leader.IP, leader.Port)
validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1} validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1}
_, validator1.PubKey = utils.GenKeyBLS(validator1.IP, validator1.Port) _, validator1.PubKey = utils.GenKey(validator1.IP, validator1.Port)
validator2 := p2p.Peer{IP: "127.0.0.1", Port: "7786", ValidatorID: 2} validator2 := p2p.Peer{IP: "127.0.0.1", Port: "7786", ValidatorID: 2}
_, validator2.PubKey = utils.GenKeyBLS(validator2.IP, validator2.Port) _, validator2.PubKey = utils.GenKey(validator2.IP, validator2.Port)
validator3 := p2p.Peer{IP: "127.0.0.1", Port: "7788", ValidatorID: 3} validator3 := p2p.Peer{IP: "127.0.0.1", Port: "7788", ValidatorID: 3}
_, validator3.PubKey = utils.GenKeyBLS(validator3.IP, validator3.Port) _, validator3.PubKey = utils.GenKey(validator3.IP, validator3.Port)
m := mock_host.NewMockHost(ctrl) m := mock_host.NewMockHost(ctrl)
// Asserts that the first and only call to Bar() is passed 99. // Asserts that the first and only call to Bar() is passed 99.
@ -137,14 +137,14 @@ func TestProcessMessageValidatorCommitted(test *testing.T) {
defer ctrl.Finish() defer ctrl.Finish()
leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"} leader := p2p.Peer{IP: "127.0.0.1", Port: "7782"}
_, leader.PubKey = utils.GenKeyBLS(leader.IP, leader.Port) _, leader.PubKey = utils.GenKey(leader.IP, leader.Port)
validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1} validator1 := p2p.Peer{IP: "127.0.0.1", Port: "7784", ValidatorID: 1}
_, validator1.PubKey = utils.GenKeyBLS(validator1.IP, validator1.Port) _, validator1.PubKey = utils.GenKey(validator1.IP, validator1.Port)
validator2 := p2p.Peer{IP: "127.0.0.1", Port: "7786", ValidatorID: 2} validator2 := p2p.Peer{IP: "127.0.0.1", Port: "7786", ValidatorID: 2}
_, validator2.PubKey = utils.GenKeyBLS(validator2.IP, validator2.Port) _, validator2.PubKey = utils.GenKey(validator2.IP, validator2.Port)
validator3 := p2p.Peer{IP: "127.0.0.1", Port: "7788", ValidatorID: 3} validator3 := p2p.Peer{IP: "127.0.0.1", Port: "7788", ValidatorID: 3}
_, validator3.PubKey = utils.GenKeyBLS(validator3.IP, validator3.Port) _, validator3.PubKey = utils.GenKey(validator3.IP, validator3.Port)
m := mock_host.NewMockHost(ctrl) m := mock_host.NewMockHost(ctrl)
// Asserts that the first and only call to Bar() is passed 99. // Asserts that the first and only call to Bar() is passed 99.

@ -9,9 +9,9 @@ import (
// Test the basic functionality of a BLS multi-sig mask. // Test the basic functionality of a BLS multi-sig mask.
func TestNewMask(test *testing.T) { func TestNewMask(test *testing.T) {
_, pubKey1 := utils.GenKeyBLS("127.0.0.1", "5555") _, pubKey1 := utils.GenKey("127.0.0.1", "5555")
_, pubKey2 := utils.GenKeyBLS("127.0.0.1", "6666") _, pubKey2 := utils.GenKey("127.0.0.1", "6666")
_, pubKey3 := utils.GenKeyBLS("127.0.0.1", "7777") _, pubKey3 := utils.GenKey("127.0.0.1", "7777")
mask, err := NewMask([]*bls.PublicKey{pubKey1, pubKey2, pubKey3}, pubKey1) mask, err := NewMask([]*bls.PublicKey{pubKey1, pubKey2, pubKey3}, pubKey1)

@ -1,440 +0,0 @@
/*
Package crypto implements the collective signing (CoSi) algorithm as presented in
the paper "Keeping Authorities 'Honest or Bust' with Decentralized Witness
Cosigning" by Ewa Syta et al. See https://arxiv.org/abs/1503.08768. This
package only provides the functionality for the cryptographic operations of
CoSi. All network-related operations have to be handled elsewhere. Below we
describe a high-level overview of the CoSi protocol (using a star communication
topology). We refer to the research paper for further details on communication
over trees, exception mechanisms and signature verification policies.
The CoSi protocol has four phases executed between a list of participants P
having a protocol leader (index i = 0) and a list of other nodes (index i > 0).
The secret key of node i is denoted by a_i and the public key by A_i = [a_i]G
(where G is the base point of the underlying group and [...] denotes scalar
multiplication). The aggregate public key is given as A = \sum{i P}(A_i).
1. Announcement: The leader broadcasts an announcement to the other nodes
optionally including the message M to be signed. Upon receiving an announcement
message, a node starts its commitment phase.
2. Commitment: Each node i (including the leader) picks a random scalar v_i,
computes its commitment V_i = [v_i]G and sends V_i back to the leader. The
leader waits until it has received enough commitments (according to some
policy) from the other nodes or a timer has run out. Let P' be the nodes that
have sent their commitments. The leader computes an aggregate commitment V from
all commitments he has received, i.e., V = \sum{j P'}(V_j) and creates a
participation bitmask Z. The leader then broadcasts V and Z to the other
participations together with the message M if it was not sent in phase 1. Upon
receiving a commitment message, a node starts the challenge phase.
3. Challenge: Each node i computes the collective challenge c = H(V || A || M)
using a cryptographic hash function H (here: SHA512), computes its
response r_i = v_i + c*a_i and sends it back to the leader.
4. Response: The leader waits until he has received replies from all nodes in
P' or a timer has run out. If he has not enough replies he aborts. Finally,
the leader computes the aggregate response r = \sum{j P'}(r_j) and publishes
(V,r,Z) as the signature for the message M.
*/
package crypto
import (
"errors"
"fmt"
"github.com/dedis/kyber"
)
// Commit returns a random scalar v, generated from the given suite,
// and a corresponding commitment V = [v]G. If the given cipher stream is nil,
// a random stream is used.
func Commit(suite Suite) (v kyber.Scalar, V kyber.Point) {
random := suite.Scalar().Pick(suite.RandomStream())
commitment := suite.Point().Mul(random, nil)
return random, commitment
}
// AggregateCommitments returns the sum of the given commitments and the
// bitwise OR of the corresponding masks.
func AggregateCommitments(suite Suite, commitments []kyber.Point, masks [][]byte) (sum kyber.Point, commits []byte, err error) {
if len(commitments) != len(masks) {
return nil, nil, errors.New("mismatching lengths of commitment and mask slices")
}
aggCom := suite.Point().Null()
aggMask := make([]byte, len(masks[0]))
for i := range commitments {
aggCom = suite.Point().Add(aggCom, commitments[i])
aggMask, err = AggregateMasks(aggMask, masks[i])
if err != nil {
return nil, nil, err
}
}
return aggCom, aggMask, nil
}
// AggregateCommitmentsOnly returns the sum of the given commitments.
func AggregateCommitmentsOnly(suite Suite, commitments []kyber.Point) kyber.Point {
aggCom := suite.Point().Null()
for i := range commitments {
aggCom = suite.Point().Add(aggCom, commitments[i])
}
return aggCom
}
// Challenge creates the collective challenge from the given aggregate
// commitment V, aggregate public key A, and message M, i.e., it returns
// c = H(V || A || M).
func Challenge(suite Suite, commitment, public kyber.Point, message []byte) (kyber.Scalar, error) {
if commitment == nil {
return nil, errors.New("no commitment provided")
}
if message == nil {
return nil, errors.New("no message provided")
}
hash := suite.Hash()
if _, err := commitment.MarshalTo(hash); err != nil {
return nil, err
}
if _, err := public.MarshalTo(hash); err != nil {
return nil, err
}
hash.Write(message)
return suite.Scalar().SetBytes(hash.Sum(nil)), nil
}
// Response creates the response from the given random scalar v, (collective)
// challenge c, and private key a, i.e., it returns r = v + c*a.
func Response(suite Suite, private, random, challenge kyber.Scalar) (kyber.Scalar, error) {
if private == nil {
return nil, errors.New("no private key provided")
}
if random == nil {
return nil, errors.New("no random scalar provided")
}
if challenge == nil {
return nil, errors.New("no challenge provided")
}
// TODO: figure out why in the paper it says r = v - cx
ca := suite.Scalar().Mul(private, challenge)
return ca.Add(random, ca), nil
}
// AggregateResponses returns the sum of given responses.
func AggregateResponses(suite Suite, responses []kyber.Scalar) (kyber.Scalar, error) {
if responses == nil {
return nil, errors.New("no responses provided")
}
r := suite.Scalar().Zero()
for i := range responses {
r = r.Add(r, responses[i])
}
return r, nil
}
// Sign returns the collective signature from the given (aggregate) commitment
// V, (aggregate) response r, and participation bitmask Z using the EdDSA
// format, i.e., the signature is V || r || Z.
func Sign(suite Suite, commitment kyber.Point, response kyber.Scalar, mask *Mask) ([]byte, error) {
if commitment == nil {
return nil, errors.New("no commitment provided")
}
if response == nil {
return nil, errors.New("no response provided")
}
if mask == nil {
return nil, errors.New("no mask provided")
}
lenV := suite.PointLen()
lenSig := lenV + suite.ScalarLen()
VB, err := commitment.MarshalBinary()
if err != nil {
return nil, errors.New("marshalling of commitment failed")
}
RB, err := response.MarshalBinary()
if err != nil {
return nil, errors.New("marshalling of signature failed")
}
sig := make([]byte, lenSig+mask.Len())
copy(sig[:], VB)
copy(sig[lenV:lenSig], RB)
copy(sig[lenSig:], mask.mask)
return sig, nil
}
// Verify checks the given cosignature on the provided message using the list
// of public keys and cosigning policy.
func Verify(suite Suite, publics []kyber.Point, message, sig []byte, policy Policy) error {
if publics == nil {
return errors.New("no public keys provided")
}
if message == nil {
return errors.New("no message provided")
}
if sig == nil {
return errors.New("no signature provided")
}
if policy == nil {
policy = CompletePolicy{}
}
lenCom := suite.PointLen()
VBuff := sig[:lenCom]
V := suite.Point()
if err := V.UnmarshalBinary(VBuff); err != nil {
return errors.New("unmarshalling of commitment failed")
}
// Unpack the aggregate response
lenRes := lenCom + suite.ScalarLen()
rBuff := sig[lenCom:lenRes]
r := suite.Scalar().SetBytes(rBuff)
// Unpack the participation mask and get the aggregate public key
mask, err := NewMask(suite, publics, nil)
if err != nil {
return err
}
mask.SetMask(sig[lenRes:])
A := mask.AggregatePublic
ABuff, err := A.MarshalBinary()
if err != nil {
return errors.New("marshalling of aggregate public key failed")
}
// Recompute the challenge
hash := suite.Hash()
hash.Write(VBuff)
hash.Write(ABuff)
hash.Write(message)
buff := hash.Sum(nil)
k := suite.Scalar().SetBytes(buff)
// k * -aggPublic + s * B = k*-A + s*B
// from s = k * a + r => s * B = k * a * B + r * B <=> s*B = k*A + r*B
// <=> s*B + k*-A = r*B
minusPublic := suite.Point().Neg(A)
kA := suite.Point().Mul(k, minusPublic)
sB := suite.Point().Mul(r, nil)
left := suite.Point().Add(kA, sB)
if !left.Equal(V) {
return errors.New("recreated response is different from signature")
}
if !policy.Check(mask) {
return errors.New("the policy is not fulfilled")
}
return nil
}
// Mask represents a cosigning participation bitmask.
type Mask struct {
mask []byte
publics []kyber.Point
AggregatePublic kyber.Point
}
// NewMask returns a new participation bitmask for cosigning where all
// cosigners are disabled by default. If a public key is given it verifies that
// it is present in the list of keys and sets the corresponding index in the
// bitmask to 1 (enabled).
func NewMask(suite Suite, publics []kyber.Point, myKey kyber.Point) (*Mask, error) {
m := &Mask{
publics: publics,
}
m.mask = make([]byte, m.Len())
m.AggregatePublic = suite.Point().Null()
if myKey != nil {
found := false
for i, key := range publics {
if key.Equal(myKey) {
m.SetBit(i, true)
found = true
break
}
}
if !found {
return nil, errors.New("key not found")
}
}
return m, nil
}
// Mask returns a copy of the participation bitmask.
func (m *Mask) Mask() []byte {
clone := make([]byte, len(m.mask))
copy(clone[:], m.mask)
return clone
}
// Len returns the mask length in bytes.
func (m *Mask) Len() int {
return (len(m.publics) + 7) >> 3
}
// SetMask sets the participation bitmask according to the given byte slice
// interpreted in little-endian order, i.e., bits 0-7 of byte 0 correspond to
// cosigners 0-7, bits 0-7 of byte 1 correspond to cosigners 8-15, etc.
func (m *Mask) SetMask(mask []byte) error {
if m.Len() != len(mask) {
return fmt.Errorf("mismatching mask lengths")
}
for i := range m.publics {
byt := i >> 3
msk := byte(1) << uint(i&7)
if ((m.mask[byt] & msk) == 0) && ((mask[byt] & msk) != 0) {
m.mask[byt] ^= msk // flip bit in mask from 0 to 1
m.AggregatePublic.Add(m.AggregatePublic, m.publics[i])
}
if ((m.mask[byt] & msk) != 0) && ((mask[byt] & msk) == 0) {
m.mask[byt] ^= msk // flip bit in mask from 1 to 0
m.AggregatePublic.Sub(m.AggregatePublic, m.publics[i])
}
}
return nil
}
// SetBit enables (enable: true) or disables (enable: false) the bit
// in the participation mask of the given cosigner.
func (m *Mask) SetBit(i int, enable bool) error {
if i >= len(m.publics) {
return errors.New("index out of range")
}
byt := i >> 3
msk := byte(1) << uint(i&7)
if ((m.mask[byt] & msk) == 0) && enable {
m.mask[byt] ^= msk // flip bit in mask from 0 to 1
m.AggregatePublic.Add(m.AggregatePublic, m.publics[i])
}
if ((m.mask[byt] & msk) != 0) && !enable {
m.mask[byt] ^= msk // flip bit in mask from 1 to 0
m.AggregatePublic.Sub(m.AggregatePublic, m.publics[i])
}
return nil
}
// GetPubKeyFromMask will return pubkeys which masked either zero or one depending on the flag
// it is used to show which signers are signed or not in the cosign message
func (m *Mask) GetPubKeyFromMask(flag bool) []kyber.Point {
pubKeys := []kyber.Point{}
for i := range m.publics {
byt := i >> 3
msk := byte(1) << uint(i&7)
if flag == true {
if (m.mask[byt] & msk) != 0 {
pubKeys = append(pubKeys, m.publics[i])
}
} else {
if (m.mask[byt] & msk) == 0 {
pubKeys = append(pubKeys, m.publics[i])
}
}
}
return pubKeys
}
// IndexEnabled checks whether the given index is enabled in the mask or not.
func (m *Mask) IndexEnabled(i int) (bool, error) {
if i >= len(m.publics) {
return false, errors.New("index out of range")
}
byt := i >> 3
msk := byte(1) << uint(i&7)
return ((m.mask[byt] & msk) != 0), nil
}
// KeyEnabled checks whether the index, corresponding to the given key, is
// enabled in the mask or not.
func (m *Mask) KeyEnabled(public kyber.Point) (bool, error) {
for i, key := range m.publics {
if key.Equal(public) {
return m.IndexEnabled(i)
}
}
return false, errors.New("key not found")
}
// SetKey set the bit in the mask for the given cosigner
func (m *Mask) SetKey(public kyber.Point, enable bool) error {
for i, key := range m.publics {
if key.Equal(public) {
return m.SetBit(i, enable)
}
}
return errors.New("key not found")
}
// CountEnabled returns the number of enabled nodes in the CoSi participation
// mask.
func (m *Mask) CountEnabled() int {
// hw is hamming weight
hw := 0
for i := range m.publics {
byt := i >> 3
msk := byte(1) << uint(i&7)
if (m.mask[byt] & msk) != 0 {
hw++
}
}
return hw
}
// CountTotal returns the total number of nodes this CoSi instance knows.
func (m *Mask) CountTotal() int {
return len(m.publics)
}
// AggregateMasks computes the bitwise OR of the two given participation masks.
func AggregateMasks(a, b []byte) ([]byte, error) {
if len(a) != len(b) {
return nil, errors.New("mismatching mask lengths")
}
m := make([]byte, len(a))
for i := range m {
m[i] = a[i] | b[i]
}
return m, nil
}
// Policy represents a fully customizable cosigning policy deciding what
// cosigner sets are and aren't sufficient for a collective signature to be
// considered acceptable to a verifier. The Check method may inspect the set of
// participants that cosigned by invoking cosi.Mask and/or cosi.MaskBit, and may
// use any other relevant contextual information (e.g., how security-critical
// the operation relying on the collective signature is) in determining whether
// the collective signature was produced by an acceptable set of cosigners.
type Policy interface {
Check(m *Mask) bool
}
// CompletePolicy is the default policy requiring that all participants have
// cosigned to make a collective signature valid.
type CompletePolicy struct {
}
// Check verifies that all participants have contributed to a collective
// signature.
func (p CompletePolicy) Check(m *Mask) bool {
return m.CountEnabled() == m.CountTotal()
}
// ThresholdPolicy allows to specify a simple t-of-n policy requring that at
// least the given threshold number of participants t have cosigned to make a
// collective signature valid.
type ThresholdPolicy struct {
thold int
}
// NewThresholdPolicy returns a new ThresholdPolicy with the given threshold.
func NewThresholdPolicy(thold int) *ThresholdPolicy {
return &ThresholdPolicy{thold: thold}
}
// Check verifies that at least a threshold number of participants have
// contributed to a collective signature.
func (p ThresholdPolicy) Check(m *Mask) bool {
return m.CountEnabled() >= p.thold
}

@ -1,6 +0,0 @@
package crypto
import "github.com/dedis/kyber/group/edwards25519"
// Ed25519Curve value gets initialized.
var Ed25519Curve = edwards25519.NewBlakeSHA256Ed25519()

@ -4,9 +4,7 @@ import (
"crypto/sha256" "crypto/sha256"
"encoding/binary" "encoding/binary"
"github.com/dedis/kyber"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/crypto"
) )
func init() { func init() {
@ -42,11 +40,6 @@ func GetAddressFromInt(value int) [20]byte {
return GetAddressFromPrivateKeyBytes(priKey) return GetAddressFromPrivateKeyBytes(priKey)
} }
// GetPrivateKeyScalarFromInt return private key scalar.
func GetPrivateKeyScalarFromInt(value int) kyber.Scalar {
return crypto.Ed25519Curve.Scalar().SetInt64(int64(value))
}
// GetBLSPrivateKeyFromInt returns bls private key // GetBLSPrivateKeyFromInt returns bls private key
func GetBLSPrivateKeyFromInt(value int) *bls.SecretKey { func GetBLSPrivateKeyFromInt(value int) *bls.SecretKey {
priKey := [32]byte{} priKey := [32]byte{}
@ -55,36 +48,3 @@ func GetBLSPrivateKeyFromInt(value int) *bls.SecretKey {
privateKey.SetLittleEndian(priKey[:]) privateKey.SetLittleEndian(priKey[:])
return &privateKey return &privateKey
} }
// GetPrivateKeyFromInt returns private key in bytes given an interger.
func GetPrivateKeyFromInt(value int) [32]byte {
priKey, err := crypto.Ed25519Curve.Scalar().SetInt64(int64(value)).MarshalBinary()
priKeyBytes := [32]byte{}
if err == nil {
copy(priKeyBytes[:], priKey[:])
}
return priKeyBytes
}
// GetPublicKeyFromPrivateKey return public key from private key.
func GetPublicKeyFromPrivateKey(priKey [32]byte) kyber.Point {
suite := crypto.Ed25519Curve
scalar := suite.Scalar()
scalar.UnmarshalBinary(priKey[:])
return suite.Point().Mul(scalar, nil)
}
// GetPublicKeyFromScalar is the same as GetPublicKeyFromPrivateKey, but it directly works on kyber.Scalar object.
func GetPublicKeyFromScalar(priKey kyber.Scalar) kyber.Point {
return crypto.Ed25519Curve.Point().Mul(priKey, nil)
}
// GetBytesFromPublicKey converts public key point to bytes
func GetBytesFromPublicKey(pubKey kyber.Point) [32]byte {
bytes, err := pubKey.MarshalBinary()
result := [32]byte{}
if err == nil {
copy(result[:], bytes)
}
return result
}

@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/crypto"
) )
func TestGetAddressFromPublicKey(test *testing.T) { func TestGetAddressFromPublicKey(test *testing.T) {
@ -22,37 +21,3 @@ func TestGetAddressFromPublicKey(test *testing.T) {
test.Error("two public address should be equal") test.Error("two public address should be equal")
} }
} }
func TestGetPublicKeyFromPrivateKey(test *testing.T) {
suite := crypto.Ed25519Curve
t := time.Now().UnixNano()
scalar := suite.Scalar().SetInt64(t)
pubKey1 := GetPublicKeyFromScalar(scalar)
bytes := [32]byte{}
tmp, err := scalar.MarshalBinary()
copy(bytes[:], tmp)
if err != nil {
test.Error("unable to marshal private key to binary")
}
pubKey2 := GetPublicKeyFromPrivateKey(bytes)
if !reflect.DeepEqual(pubKey1, pubKey2) {
test.Error("two public keys should be equal")
}
}
func TestGetPrivateKeyFromInt(test *testing.T) {
t := int(time.Now().UnixNano())
priKey1 := GetPrivateKeyFromInt(t)
priKeyScalar := GetPrivateKeyScalarFromInt(t)
tmp, err := priKeyScalar.MarshalBinary()
priKey2 := [32]byte{}
copy(priKey2[:], tmp)
if err != nil {
test.Error("unable to marshal private key to binary")
}
if !reflect.DeepEqual(priKey1, priKey2) {
test.Error("two private keys should be equal")
}
}

@ -1,10 +0,0 @@
package crypto
import "github.com/dedis/kyber"
// Suite specifies the cryptographic building blocks required for the cosi package.
type Suite interface {
kyber.Group
kyber.HashFactory
kyber.Random
}

@ -39,7 +39,7 @@ type NewNode struct {
// New candidatenode initialization // New candidatenode initialization
func New(ip string, port string, nodePk p2p_crypto.PrivKey) *NewNode { func New(ip string, port string, nodePk p2p_crypto.PrivKey) *NewNode {
priKey, pubKey := utils.GenKeyBLS(ip, port) priKey, pubKey := utils.GenKey(ip, port)
var node NewNode var node NewNode
var err error var err error
node.PubK = pubKey node.PubK = pubKey
@ -131,7 +131,7 @@ func (node *NewNode) processShardInfo(msgPayload []byte) bool {
leaderPeer.PubKey = &bls.PublicKey{} leaderPeer.PubKey = &bls.PublicKey{}
err = leaderPeer.PubKey.Deserialize(v.PubKey[:]) err = leaderPeer.PubKey.Deserialize(v.PubKey[:])
if err != nil { if err != nil {
node.log.Error("Could not unmarshall leaders public key from binary to kyber.point") node.log.Error("Could not unmarshall leaders public key from binary")
} }
node.Leaders[uint32(n)] = leaderPeer node.Leaders[uint32(n)] = leaderPeer
} }

@ -13,10 +13,7 @@ import (
"strconv" "strconv"
"sync" "sync"
"github.com/dedis/kyber"
"github.com/harmony-one/bls/ffi/go/bls" "github.com/harmony-one/bls/ffi/go/bls"
"github.com/harmony-one/harmony/crypto"
"github.com/harmony-one/harmony/crypto/pki"
"github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/p2p"
p2p_crypto "github.com/libp2p/go-libp2p-crypto" p2p_crypto "github.com/libp2p/go-libp2p-crypto"
) )
@ -75,16 +72,8 @@ func GetUniqueIDFromIPPort(ip, port string) uint32 {
return uint32(value) return uint32(value)
} }
// GenKey generates a key given ip and port. // GenKey generates a bls key pair given ip and port.
func GenKey(ip, port string) (kyber.Scalar, kyber.Point) { func GenKey(ip, port string) (*bls.SecretKey, *bls.PublicKey) {
priKey := crypto.Ed25519Curve.Scalar().SetInt64(int64(GetUniqueIDFromIPPort(ip, port))) // TODO: figure out why using a random hash value doesn't work for private key (schnorr)
pubKey := pki.GetPublicKeyFromScalar(priKey)
return priKey, pubKey
}
// GenKeyBLS generates a bls key pair given ip and port.
func GenKeyBLS(ip, port string) (*bls.SecretKey, *bls.PublicKey) {
nodeIDBytes := make([]byte, 32) nodeIDBytes := make([]byte, 32)
binary.LittleEndian.PutUint32(nodeIDBytes, GetUniqueIDFromIPPort(ip, port)) binary.LittleEndian.PutUint32(nodeIDBytes, GetUniqueIDFromIPPort(ip, port))
privateKey := bls.SecretKey{} privateKey := bls.SecretKey{}

@ -48,12 +48,7 @@ func TestAllocateShard(t *testing.T) {
// Test for GenKey // Test for GenKey
func TestGenKey(t *testing.T) { func TestGenKey(t *testing.T) {
GenKey("3.3.3.3", "3456") priKey, pubKey := GenKey("3.3.3.3", "3456")
}
// Test for GenKeyBLS
func TestGenKeyBLS(t *testing.T) {
priKey, pubKey := GenKeyBLS("3.3.3.3", "3456")
if priKey == nil || pubKey == nil { if priKey == nil || pubKey == nil {
t.Error("Failed to create keys for BLS sig") t.Error("Failed to create keys for BLS sig")
} }

@ -11,7 +11,7 @@ import (
) )
func TestNodeStreamHandler(t *testing.T) { func TestNodeStreamHandler(t *testing.T) {
_, pubKey := utils.GenKeyBLS("1", "2") _, pubKey := utils.GenKey("1", "2")
leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey}
validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
@ -35,7 +35,7 @@ func TestNodeStreamHandler(t *testing.T) {
} }
func TestAddNewBlock(t *testing.T) { func TestAddNewBlock(t *testing.T) {
_, pubKey := utils.GenKeyBLS("1", "2") _, pubKey := utils.GenKey("1", "2")
leader := p2p.Peer{IP: "127.0.0.1", Port: "9882", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "9882", PubKey: pubKey}
validator := p2p.Peer{IP: "127.0.0.1", Port: "9885"} validator := p2p.Peer{IP: "127.0.0.1", Port: "9885"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
@ -58,7 +58,7 @@ func TestAddNewBlock(t *testing.T) {
} }
func TestVerifyNewBlock(t *testing.T) { func TestVerifyNewBlock(t *testing.T) {
_, pubKey := utils.GenKeyBLS("1", "2") _, pubKey := utils.GenKey("1", "2")
leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey}
validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")

@ -15,7 +15,7 @@ import (
) )
func TestNewNode(t *testing.T) { func TestNewNode(t *testing.T) {
_, pubKey := utils.GenKeyBLS("1", "2") _, pubKey := utils.GenKey("1", "2")
leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey}
validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
@ -39,7 +39,7 @@ func TestNewNode(t *testing.T) {
} }
func TestGetSyncingPeers(t *testing.T) { func TestGetSyncingPeers(t *testing.T) {
_, pubKey := utils.GenKeyBLS("1", "2") _, pubKey := utils.GenKey("1", "2")
leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "8882", PubKey: pubKey}
validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"} validator := p2p.Peer{IP: "127.0.0.1", Port: "8885"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
@ -82,7 +82,7 @@ func TestAddPeers(t *testing.T) {
ValidatorID: 2, ValidatorID: 2,
}, },
} }
_, pubKey := utils.GenKeyBLS("1", "2") _, pubKey := utils.GenKey("1", "2")
leader := p2p.Peer{IP: "127.0.0.1", Port: "8982", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "8982", PubKey: pubKey}
validator := p2p.Peer{IP: "127.0.0.1", Port: "8985"} validator := p2p.Peer{IP: "127.0.0.1", Port: "8985"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")
@ -156,7 +156,7 @@ func exitServer() {
} }
func TestPingPongHandler(t *testing.T) { func TestPingPongHandler(t *testing.T) {
_, pubKey := utils.GenKeyBLS("127.0.0.1", "8881") _, pubKey := utils.GenKey("127.0.0.1", "8881")
leader := p2p.Peer{IP: "127.0.0.1", Port: "8881", PubKey: pubKey} leader := p2p.Peer{IP: "127.0.0.1", Port: "8881", PubKey: pubKey}
// validator := p2p.Peer{IP: "127.0.0.1", Port: "9991"} // validator := p2p.Peer{IP: "127.0.0.1", Port: "9991"}
priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902") priKey, _, _ := utils.GenKeyP2P("127.0.0.1", "9902")

1
vendor/github.com/dedis/kyber generated vendored

@ -1 +0,0 @@
Subproject commit 5cc64601919b0945d10aba014129cdfef5fdda46
Loading…
Cancel
Save