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}