arnaucube
arnaucube/cryptofunPublic Self-hosted repository
cryptofun/bls/bls.go
bls/bls.goRaw
  1package bls
  2
  3import (
  4	"crypto/rand"
  5	"crypto/sha256"
  6	"math/big"
  7
  8	"github.com/arnaucube/go-snark/bn128"
  9)
 10
 11// this BLS implementation uses the Go implementation of the BN128 pairing github.com/arnaucube/go-snark/bn128
 12
 13const bits = 2048
 14
 15// BLS is the data structure of the BLS signature scheme, including the BN128 pairing curve
 16type BLS struct {
 17	Bn bn128.Bn128
 18}
 19type BLSKeys struct {
 20	PrivK *big.Int
 21	PubK  [3]*big.Int
 22}
 23
 24// NewBLS generates a new BLS scheme
 25func NewBLS() (BLS, error) {
 26	bn, err := bn128.NewBn128()
 27	if err != nil {
 28		return BLS{}, err
 29	}
 30	bls := BLS{}
 31	bls.Bn = bn
 32	return bls, nil
 33}
 34
 35// NewKeys generate new Private Key and Public Key
 36func (bls BLS) NewKeys() (BLSKeys, error) {
 37	var err error
 38	k := BLSKeys{}
 39	k.PrivK, err = rand.Prime(rand.Reader, bits)
 40	if err != nil {
 41		return BLSKeys{}, err
 42	}
 43
 44	// pubK = pk * G
 45	k.PubK = bls.Bn.G1.MulScalar(bls.Bn.G1.G, k.PrivK)
 46	return k, nil
 47}
 48
 49// Hash hashes a message m
 50func (bls BLS) Hash(m []byte) [3][2]*big.Int {
 51	h := sha256.New()
 52	h.Write(m)
 53	hash := h.Sum(nil)
 54	r := new(big.Int).SetBytes(hash)
 55	// get point over the curve
 56	point := bls.Bn.G2.MulScalar(bls.Bn.G2.G, r)
 57	return point
 58}
 59
 60// Sign performs the BLS signature of a message m
 61func (bls BLS) Sign(privK *big.Int, m []byte) [3][2]*big.Int {
 62	// s = pk * H(m)
 63	h := bls.Hash(m)
 64	sig := bls.Bn.G2.MulScalar(h, privK)
 65	return sig
 66}
 67
 68// Verify checks the signature of a message m with the given Public Key
 69func (bls BLS) Verify(m []byte, sig [3][2]*big.Int, pubK [3]*big.Int) bool {
 70	// checks e(P, G) == e(G, s)
 71	p1, err := bls.Bn.Pairing(pubK, bls.Hash(m))
 72	if err != nil {
 73		return false
 74	}
 75	p2, err := bls.Bn.Pairing(bls.Bn.G1.G, sig)
 76	if err != nil {
 77		return false
 78	}
 79
 80	return bls.Bn.Fq12.Equal(p1, p2)
 81}
 82
 83// AggregateSignatures
 84// s = s0 + s1 + s2 ...
 85func (bls BLS) AggregateSignatures(signatures ...[3][2]*big.Int) [3][2]*big.Int {
 86	aggr := signatures[0]
 87	for i := 1; i < len(signatures); i++ {
 88		aggr = bls.Bn.G2.Add(aggr, signatures[i])
 89	}
 90	return aggr
 91}
 92
 93// VerifyAggregatedSignatures
 94// ê(G,S) == ê(P, H(m))
 95// ê(G, s0+s1+s2...) == ê(p0, H(m)) x ê(p1, H(m)) x ê(p2, H(m)) ...
 96func (bls BLS) VerifyAggregatedSignatures(aggrsig [3][2]*big.Int, pubKArray [][3]*big.Int, m []byte) bool {
 97	pairingGS, err := bls.Bn.Pairing(bls.Bn.G1.G, aggrsig)
 98	if err != nil {
 99		return false
100	}
101
102	pairingsMul, err := bls.Bn.Pairing(pubKArray[0], bls.Hash(m))
103	if err != nil {
104		return false
105	}
106	for i := 1; i < len(pubKArray); i++ {
107		e, err := bls.Bn.Pairing(pubKArray[i], bls.Hash(m))
108		if err != nil {
109			return false
110		}
111		pairingsMul = bls.Bn.Fq12.Mul(pairingsMul, e)
112	}
113
114	if !bls.Bn.Fq12.Equal(pairingGS, pairingsMul) {
115		return false
116	}
117	return true
118}