/
bngroup.go
152 lines (139 loc) · 4.16 KB
/
bngroup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package crypto
import (
"math/big"
"github.com/alicenet/alicenet/constants"
bn256 "github.com/alicenet/alicenet/crypto/bn256/cloudflare"
)
// BNGroupSigner creates cryptographic signatures using the bn256 curve.
type BNGroupSigner struct {
privk *big.Int
pubk *bn256.G2
groupPubk *bn256.G2
}
// SetPrivk sets the private key of the BNGroupSigner.
func (bns *BNGroupSigner) SetPrivk(privk []byte) error {
if bns == nil {
return ErrInvalid
}
bns.privk = new(big.Int).SetBytes(privk)
bns.privk.Mod(bns.privk, bn256.Order)
bns.pubk = new(bn256.G2).ScalarBaseMult(bns.privk)
return nil
}
// SetGroupPubk will set the public key of the entire group;
// this is also called the master public key.
func (bns *BNGroupSigner) SetGroupPubk(groupPubk []byte) error {
if bns == nil {
return ErrInvalid
}
pubkpoint := new(bn256.G2)
_, err := pubkpoint.Unmarshal(groupPubk)
if err != nil {
return err
}
bns.groupPubk = pubkpoint
return nil
}
// VerifyGroupShares checks groupShares to ensure that it can be used as
// a valid ordering of the validators to correctly compute valid
// group signatures.
//
// We first check to make sure that each public key is a valid element of
// bn256.G2. From there, we also check to make sure that the byte slice did
// not appear in a previous position; to do this, we use a hash map.
func (bns *BNGroupSigner) VerifyGroupShares(groupShares [][]byte) error {
var keyArr [constants.CurveBN256EthPubkeyLen]byte
pubk := new(bn256.G2)
kmap := make(map[[constants.CurveBN256EthPubkeyLen]byte]bool)
for k := 0; k < len(groupShares); k++ {
sliceK := groupShares[k]
// Ensure public keys are valid
_, err := pubk.Unmarshal(sliceK)
if err != nil {
return err
}
copy(keyArr[:], sliceK)
// Ensure no repeated public keys
if !kmap[keyArr] {
kmap[keyArr] = true
} else {
return ErrInvalidPubkeyShares
}
}
return nil
}
// PubkeyShare returns the marshalled public key of the BNGroupSigner
func (bns *BNGroupSigner) PubkeyShare() ([]byte, error) {
if bns == nil || bns.privk == nil {
return nil, ErrPrivkNotSet
}
return bns.pubk.Marshal(), nil
}
// PubkeyGroup returns the marshalled public key of the group
// (master public key).
func (bns *BNGroupSigner) PubkeyGroup() ([]byte, error) {
if bns == nil || bns.groupPubk == nil {
return nil, ErrPubkeyGroupNotSet
}
return bns.groupPubk.Marshal(), nil
}
// Sign will generate a signature for msg using the private key of the
// BNGroupSigner; this signature can be aggregated to form a valid
// group signature.
func (bns *BNGroupSigner) Sign(msg []byte) ([]byte, error) {
if bns == nil {
return nil, ErrInvalid
}
sigpoint, err := bn256.Sign(msg, bns.privk, bn256.HashToG1)
if err != nil {
return nil, err
}
return bn256.MarshalSignature(sigpoint, bns.pubk)
}
// Aggregate attempts to combine the slice of signatures in sigs into
// a group signature.
func (bns *BNGroupSigner) Aggregate(sigs [][]byte, groupShares [][]byte) ([]byte, error) {
if bns == nil {
return nil, ErrInvalid
}
err := bns.VerifyGroupShares(groupShares)
if err != nil {
return nil, err
}
if bns.groupPubk == nil {
return nil, ErrPubkeyGroupNotSet
}
aggSig, err := bn256.AggregateMarshalledSignatures(sigs, groupShares, CalcThreshold(len(groupShares)))
if err != nil {
return nil, err
}
return bn256.MarshalSignature(aggSig, bns.groupPubk)
}
// BNGroupValidator is the object that performs cryptographic validation of
// BNGroupSigner signatures.
type BNGroupValidator struct {
}
// Validate will validate a BNGroupSigner signature or group signature for msg.
func (bnv *BNGroupValidator) Validate(msg []byte, sig []byte) ([]byte, error) {
pubkey, signature, err := bn256.UnmarshalSignature(sig)
if err != nil {
return nil, err
}
ok, err := bn256.Verify(msg, signature, pubkey, bn256.HashToG1)
if err != nil {
return nil, err
}
if !ok {
return nil, ErrInvalidSignature
}
pubkeyBytes := pubkey.Marshal()
return pubkeyBytes, nil
}
// PubkeyFromSig returns the public key of the signer from the signature.
func (bnv *BNGroupValidator) PubkeyFromSig(sig []byte) ([]byte, error) {
pubkey, _, err := bn256.UnmarshalSignature(sig)
if err != nil {
return nil, err
}
return pubkey.Marshal(), nil
}