Browse Source

bls: doing aggregated signatures

master
arnaucube 6 years ago
parent
commit
f5d913b6a7
3 changed files with 86 additions and 19 deletions
  1. +1
    -1
      bls/README.md
  2. +54
    -10
      bls/bls.go
  3. +31
    -8
      bls/bls_test.go

+ 1
- 1
bls/README.md

@ -2,7 +2,7 @@
Boneh–Lynn–Shacham (BLS) signature scheme implemented in Go. Boneh–Lynn–Shacham (BLS) signature scheme implemented in Go.
https://en.wikipedia.org/wiki/Boneh%E2%80%93Lynn%E2%80%93Shacham 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 ### Usage
```go ```go

+ 54
- 10
bls/bls.go

@ -3,6 +3,7 @@ package bls
import ( import (
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"fmt"
"math/big" "math/big"
"github.com/arnaucube/go-snark/bn128" "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 // BLS is the data structure of the BLS signature scheme, including the BN128 pairing curve
type BLS struct { type BLS struct {
Bn bn128.Bn128
Bn bn128.Bn128
}
type BLSKeys struct {
PrivK *big.Int PrivK *big.Int
PubK [3]*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() bn, err := bn128.NewBn128()
if err != nil { if err != nil {
return BLS{}, err return BLS{}, err
} }
bls := BLS{} bls := BLS{}
bls.Bn = bn 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 { if err != nil {
return BLS{}, err
return BLSKeys{}, err
} }
// pubK = pk * G // 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 // 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 // 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) // s = pk * H(m)
h := bls.Hash(m) h := bls.Hash(m)
sig := bls.Bn.G2.MulScalar(h, bls.PrivK)
sig := bls.Bn.G2.MulScalar(h, privK)
return sig return sig
} }
// Verify checks the signature of a message m with the given Public Key // 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 { func (bls BLS) Verify(m []byte, sig [3][2]*big.Int, pubK [3]*big.Int) bool {
// checks e(P, G) == e(G, s) // 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 { if err != nil {
return false 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) 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
}

+ 31
- 8
bls/bls_test.go

@ -2,23 +2,46 @@ package bls
import ( import (
"fmt" "fmt"
"math/big"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestBls(t *testing.T) { func TestBls(t *testing.T) {
bls, err := NewKeys()
bls, err := NewBLS()
assert.Nil(t, err)
keys0, err := bls.NewKeys()
assert.Nil(t, err) 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) 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)
} }

Loading…
Cancel
Save