Skip to content

Commit

Permalink
Implementing aggregation.
Browse files Browse the repository at this point in the history
  • Loading branch information
armfazh committed Jun 26, 2023
1 parent a2193f4 commit 04ebacc
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 45 deletions.
121 changes: 76 additions & 45 deletions sign/bls/bls.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"crypto"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
"io"

Expand Down Expand Up @@ -183,15 +182,15 @@ func KeyGen[K KeyGroup](ikm, salt, keyInfo []byte) (*PrivateKey[K], error) {
func Sign[K KeyGroup](k *PrivateKey[K], msg []byte) Signature {
switch (interface{})(k).(type) {
case *PrivateKey[G1]:
var Q G2
Q.hash(msg)
Q.g.ScalarMult(&k.key, &Q.g)
return Q.g.BytesCompressed()
var Q GG.G2
Q.Hash(msg, []byte(dstG2))
Q.ScalarMult(&k.key, &Q)
return Q.BytesCompressed()
case *PrivateKey[G2]:
var Q G1
Q.hash(msg)
Q.g.ScalarMult(&k.key, &Q.g)
return Q.g.BytesCompressed()
var Q GG.G1
Q.Hash(msg, []byte(dstG1))
Q.ScalarMult(&k.key, &Q)
return Q.BytesCompressed()
default:
panic(ErrInvalid)
}
Expand Down Expand Up @@ -237,60 +236,92 @@ func Verify[K KeyGroup](pub *PublicKey[K], msg []byte, sig Signature) bool {
return res.IsIdentity()
}

func Aggregate[K KeyGroup](sigs []Signature) (Signature, error) {
func Aggregate[K KeyGroup](k K, sigs []Signature) (Signature, error) {
if len(sigs) == 0 {
return nil, ErrAggregate
}

return nil, nil
// switch (interface{})(Aggregate[K]).(type) {
// case *func([]Signature) (Signature, error):
// var P, Q GG.G2
// P.SetIdentity()
// for _, sig := range sigs {
// if err := Q.SetBytes(sig); err != nil {
// return nil, err
// }
// P.Add(&P, &Q)
// }
// return P.BytesCompressed(), nil

// case *func([]Signature) (Signature, error):
// var P, Q GG.G1
// P.SetIdentity()
// for _, sig := range sigs {
// if err := Q.SetBytes(sig); err != nil {
// return nil, err
// }
// P.Add(&P, &Q)
// }
// return P.BytesCompressed(), nil

// default:
// panic(ErrInvalid)
// }
switch (interface{})(k).(type) {
case G1:
var P, Q GG.G2
P.SetIdentity()
for _, sig := range sigs {
if err := Q.SetBytes(sig); err != nil {
return nil, err
}
P.Add(&P, &Q)
}
return P.BytesCompressed(), nil

case G2:
var P, Q GG.G1
P.SetIdentity()
for _, sig := range sigs {
if err := Q.SetBytes(sig); err != nil {
return nil, err
}
P.Add(&P, &Q)
}
return P.BytesCompressed(), nil

default:
panic(ErrInvalid)
}
}

func VerifyAggregate[K KeyGroup](pubs []PublicKey[K], msgs [][]byte, sig Signature) bool {
func VerifyAggregate[K KeyGroup](pubs []*PublicKey[K], msgs [][]byte, aggSig Signature) bool {
if len(pubs) != len(msgs) || len(pubs) == 0 || len(msgs) == 0 {
return false
}

setMsgs := make(map[string][]PublicKey[K], len(pubs))
n := len(pubs)
listG1 := make([]*GG.G1, n+1)
listG2 := make([]*GG.G2, n+1)
listExp := make([]int, n+1)

switch (interface{})(pubs).(type) {
case []PublicKey[G1]:
case []*PublicKey[G1]:
for i := range msgs {
s := hex.EncodeToString(msgs[i])
setMsgs[s] = append(setMsgs[s], pubs[i])
listG2[i] = new(GG.G2)
listG2[i].Hash(msgs[i], []byte(dstG2))

xP := (interface{})(pubs[i].key).(G1)
listG1[i] = &xP.g
listExp[i] = 1
}
return false

case []PublicKey[G2]:
return false
listG2[n] = new(GG.G2)
err := listG2[n].SetBytes(aggSig)
if err != nil {
return false
}
listG1[n] = GG.G1Generator()
listExp[n] = -1

case []*PublicKey[G2]:
for i := range msgs {
listG1[i] = new(GG.G1)
listG1[i].Hash(msgs[i], []byte(dstG1))

xP := (interface{})(pubs[i].key).(G2)
listG2[i] = &xP.g
listExp[i] = 1
}

listG1[n] = new(GG.G1)
err := listG1[n].SetBytes(aggSig)
if err != nil {
return false
}
listG2[n] = GG.G2Generator()
listExp[n] = -1

default:
panic(ErrInvalid)
}

C := GG.ProdPairFrac(listG1, listG2, listExp)
return C.IsIdentity()
}

var (
Expand Down
56 changes: 56 additions & 0 deletions sign/bls/bls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"crypto/rand"
"encoding"
"fmt"
"testing"

"github.com/cloudflare/circl/internal/test"
Expand All @@ -17,6 +18,8 @@ func TestBls(t *testing.T) {
t.Run("G2/Marshal", testMarshalKeys[bls.G2])
t.Run("G1/Errors", testErrors[bls.G1])
t.Run("G2/Errors", testErrors[bls.G2])
t.Run("G1/Aggregation", testAggregation[bls.G1])
t.Run("G2/Aggregation", testAggregation[bls.G2])
}

func testBls[K bls.KeyGroup](t *testing.T) {
Expand Down Expand Up @@ -92,6 +95,32 @@ func testErrors[K bls.KeyGroup](t *testing.T) {
test.CheckOk(bls.Verify(pub, nil, nil) == false, "should fail: bad signature", t)
}

func testAggregation[K bls.KeyGroup](t *testing.T) {
const N = 3

ikm := [32]byte{}
_, _ = rand.Reader.Read(ikm[:])

msgs := make([][]byte, N)
sigs := make([]bls.Signature, N)
pubKeys := make([]*bls.PublicKey[K], N)

for i := range sigs {
priv, err := bls.KeyGen[K](ikm[:], nil, nil)
test.CheckNoErr(t, err, "failed to keygen")
pubKeys[i] = priv.PublicKey()

msgs[i] = []byte(fmt.Sprintf("Message number: %v", i))
sigs[i] = bls.Sign(priv, msgs[i])
}

aggSig, err := bls.Aggregate(*new(K), sigs)
test.CheckNoErr(t, err, "failed to aggregate")

ok := bls.VerifyAggregate(pubKeys, msgs, aggSig)
test.CheckOk(ok, "failed to verify aggregated signature", t)
}

func BenchmarkBls(b *testing.B) {
b.Run("G1", benchmarkBls[bls.G1])
b.Run("G2", benchmarkBls[bls.G2])
Expand All @@ -107,6 +136,18 @@ func benchmarkBls[K bls.KeyGroup](b *testing.B) {

priv, _ := bls.KeyGen[K](ikm[:], salt[:], keyInfo)

const N = 3
msgs := make([][]byte, N)
sigs := make([]bls.Signature, N)
pubKeys := make([]*bls.PublicKey[K], N)

for i := range sigs {
pubKeys[i] = priv.PublicKey()

msgs[i] = []byte(fmt.Sprintf("Message number: %v", i))
sigs[i] = bls.Sign(priv, msgs[i])
}

b.Run("Keygen", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = rand.Reader.Read(ikm[:])
Expand All @@ -129,4 +170,19 @@ func benchmarkBls[K bls.KeyGroup](b *testing.B) {
bls.Verify(pub, msg, signature)
}
})

b.Run("Aggregate3", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_, _ = bls.Aggregate(*new(K), sigs)
}
})

b.Run("VerifyAggregate3", func(b *testing.B) {
aggSig, _ := bls.Aggregate(*new(K), sigs)

b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = bls.VerifyAggregate(pubKeys, msgs, aggSig)
}
})
}

0 comments on commit 04ebacc

Please sign in to comment.