package bls
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/arnaucube/go-snark/bn128"
|
|
)
|
|
|
|
// this BLS implementation uses the Go implementation of the BN128 pairing github.com/arnaucube/go-snark/bn128
|
|
|
|
const bits = 2048
|
|
|
|
// BLS is the data structure of the BLS signature scheme, including the BN128 pairing curve
|
|
type BLS struct {
|
|
Bn bn128.Bn128
|
|
}
|
|
type BLSKeys struct {
|
|
PrivK *big.Int
|
|
PubK [3]*big.Int
|
|
}
|
|
|
|
// 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
|
|
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 BLSKeys{}, err
|
|
}
|
|
|
|
// pubK = pk * G
|
|
k.PubK = bls.Bn.G1.MulScalar(bls.Bn.G1.G, k.PrivK)
|
|
return k, nil
|
|
}
|
|
|
|
// Hash hashes a message m
|
|
func (bls BLS) Hash(m []byte) [3][2]*big.Int {
|
|
h := sha256.New()
|
|
h.Write(m)
|
|
hash := h.Sum(nil)
|
|
r := new(big.Int).SetBytes(hash)
|
|
// get point over the curve
|
|
point := bls.Bn.G2.MulScalar(bls.Bn.G2.G, r)
|
|
return point
|
|
}
|
|
|
|
// Sign performs the BLS signature of a message m
|
|
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, 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(pubK, bls.Hash(m))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
p2, err := bls.Bn.Pairing(bls.Bn.G1.G, sig)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
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
|
|
}
|