From f5d913b6a74c3e955f084c2695de0b31a7243091 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Tue, 11 Dec 2018 00:19:54 +0100 Subject: [PATCH] bls: doing aggregated signatures --- bls/README.md | 2 +- bls/bls.go | 64 +++++++++++++++++++++++++++++++++++++++++-------- bls/bls_test.go | 39 +++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/bls/README.md b/bls/README.md index f50eb03..959a445 100644 --- a/bls/README.md +++ b/bls/README.md @@ -2,7 +2,7 @@ Boneh–Lynn–Shacham (BLS) signature scheme implemented in Go. https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham -This package uses the BN128 Go implementation from https://github.com/arnaucube/go-snark/tree/master/bn128 +This package uses the BN128 Pairing Go implementation from https://github.com/arnaucube/go-snark/tree/master/bn128 ### Usage ```go diff --git a/bls/bls.go b/bls/bls.go index c5df6bd..2ab8eb9 100644 --- a/bls/bls.go +++ b/bls/bls.go @@ -3,6 +3,7 @@ package bls import ( "crypto/rand" "crypto/sha256" + "fmt" "math/big" "github.com/arnaucube/go-snark/bn128" @@ -14,27 +15,36 @@ const bits = 2048 // BLS is the data structure of the BLS signature scheme, including the BN128 pairing curve type BLS struct { - Bn bn128.Bn128 + Bn bn128.Bn128 +} +type BLSKeys struct { PrivK *big.Int PubK [3]*big.Int } -// NewKeys generate new Private Key and Public Key -func NewKeys() (BLS, error) { +// NewBLS generates a new BLS scheme +func NewBLS() (BLS, error) { bn, err := bn128.NewBn128() if err != nil { return BLS{}, err } bls := BLS{} bls.Bn = bn - bls.PrivK, err = rand.Prime(rand.Reader, bits) + return bls, nil +} + +// NewKeys generate new Private Key and Public Key +func (bls BLS) NewKeys() (BLSKeys, error) { + var err error + k := BLSKeys{} + k.PrivK, err = rand.Prime(rand.Reader, bits) if err != nil { - return BLS{}, err + return BLSKeys{}, err } // pubK = pk * G - bls.PubK = bls.Bn.G1.MulScalar(bls.Bn.G1.G, bls.PrivK) - return bls, nil + k.PubK = bls.Bn.G1.MulScalar(bls.Bn.G1.G, k.PrivK) + return k, nil } // Hash hashes a message m @@ -49,17 +59,17 @@ func (bls BLS) Hash(m []byte) [3][2]*big.Int { } // Sign performs the BLS signature of a message m -func (bls BLS) Sign(m []byte) [3][2]*big.Int { +func (bls BLS) Sign(privK *big.Int, m []byte) [3][2]*big.Int { // s = pk * H(m) h := bls.Hash(m) - sig := bls.Bn.G2.MulScalar(h, bls.PrivK) + sig := bls.Bn.G2.MulScalar(h, privK) return sig } // Verify checks the signature of a message m with the given Public Key func (bls BLS) Verify(m []byte, sig [3][2]*big.Int, pubK [3]*big.Int) bool { // checks e(P, G) == e(G, s) - p1, err := bls.Bn.Pairing(bls.PubK, bls.Hash(m)) + p1, err := bls.Bn.Pairing(pubK, bls.Hash(m)) if err != nil { return false } @@ -70,3 +80,37 @@ func (bls BLS) Verify(m []byte, sig [3][2]*big.Int, pubK [3]*big.Int) bool { return bls.Bn.Fq12.Equal(p1, p2) } + +func (bls BLS) AggregateSignatures(signatures ...[3][2]*big.Int) [3][2]*big.Int { + aggr := signatures[0] + for _, sig := range signatures { + aggr = bls.Bn.G2.Add(aggr, sig) + } + return aggr +} +func (bls BLS) VerifyAggregatedSignatures(aggrsig [3][2]*big.Int, pubKArray [][3]*big.Int, mArray [][]byte) bool { + if len(pubKArray) != len(mArray) { + fmt.Println("pubK array and msg array not with the same number of elements") + return false + } + pairingGS, err := bls.Bn.Pairing(bls.Bn.G1.G, aggrsig) + if err != nil { + return false + } + pairingsMul, err := bls.Bn.Pairing(pubKArray[0], bls.Hash(mArray[0])) + if err != nil { + return false + } + + for i := 1; i < len(pubKArray); i++ { + e, err := bls.Bn.Pairing(pubKArray[i], bls.Hash(mArray[i])) + if err != nil { + return false + } + pairingsMul = bls.Bn.Fq12.Mul(pairingsMul, e) + } + if !bls.Bn.Fq12.Equal(pairingGS, pairingsMul) { + return false + } + return true +} diff --git a/bls/bls_test.go b/bls/bls_test.go index e94a0f3..af9ec1b 100644 --- a/bls/bls_test.go +++ b/bls/bls_test.go @@ -2,23 +2,46 @@ package bls import ( "fmt" + "math/big" "testing" "github.com/stretchr/testify/assert" ) func TestBls(t *testing.T) { - bls, err := NewKeys() + bls, err := NewBLS() + assert.Nil(t, err) + keys0, err := bls.NewKeys() assert.Nil(t, err) - fmt.Println("privK:", bls.PrivK) - fmt.Println("pubK:", bls.PubK) + fmt.Println("privK:", keys0.PrivK) + fmt.Println("pubK:", keys0.PubK) - m := []byte("test") - sig := bls.Sign(m) - fmt.Println("signature:", sig) + m0 := []byte("message0") + sig0 := bls.Sign(keys0.PrivK, m0) + fmt.Println("signature:", sig0) - verified := bls.Verify(m, sig, bls.PubK) - fmt.Println("verified:", verified) + verified := bls.Verify(m0, sig0, keys0.PubK) + fmt.Println("one signature verified:", verified) assert.True(t, verified) + + // signature aggregation + keys1, err := bls.NewKeys() + assert.Nil(t, err) + m1 := []byte("message1") + sig1 := bls.Sign(keys1.PrivK, m1) + + keys2, err := bls.NewKeys() + assert.Nil(t, err) + m2 := []byte("message2") + sig2 := bls.Sign(keys2.PrivK, m2) + + aggr := bls.AggregateSignatures(sig0, sig1, sig2) + + pubKArray := [][3]*big.Int{keys0.PubK, keys1.PubK, keys2.PubK} + mArray := [][]byte{m0, m1, m2} + verified = bls.VerifyAggregatedSignatures(aggr, pubKArray, mArray) + fmt.Println("signature aggregation verified:", verified) + assert.True(t, verified) + }