forked from dedis/kyber
-
Notifications
You must be signed in to change notification settings - Fork 10
/
suite.go
221 lines (194 loc) · 5.61 KB
/
suite.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// package bn254 implements a particular bilinear group.
//
// Bilinear groups are the basis of many of the new cryptographic protocols that
// have been proposed over the past decade. They consist of a triplet of groups
// (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ
// is a generator of the respective group). That function is called a pairing
// function.
//
// This package specifically implements the Optimal Ate pairing over a 256-bit
// Barreto-Naehrig curve as described in
// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible
// with the implementation described in that paper.
//
// This package previously claimed to operate at a 128-bit security level.
// However, recent improvements in attacks mean that is no longer true. See
// https://moderncrypto.org/mail-archive/curves/2016/000740.html.
package bn254
import (
"crypto/cipher"
"hash"
"io"
"reflect"
"github.com/drand/kyber"
"github.com/drand/kyber/util/random"
"github.com/drand/kyber/xof/blake2xb"
"go.dedis.ch/fixbuf"
"golang.org/x/crypto/sha3"
)
// Suite implements the pairing.Suite interface for the BN254 bilinear pairing.
type Suite struct {
*commonSuite
g1 *groupG1
g2 *groupG2
gt *groupGT
}
func newDefaultDomainG1() []byte {
return []byte("BN254G1_XMD:KECCAK-256_SSWU_RO_")
}
func newDefaultDomainG2() []byte {
return []byte("BN254G2_XMD:KECCAK-256_SSWU_RO_")
}
// NewSuite generates and returns a new BN254 pairing suite.
func NewSuite() *Suite {
s := &Suite{commonSuite: &commonSuite{}}
s.g1 = &groupG1{
commonSuite: s.commonSuite,
dst: newDefaultDomainG1(),
}
s.g2 = &groupG2{
commonSuite: s.commonSuite,
dst: newDefaultDomainG2(),
}
s.gt = &groupGT{commonSuite: s.commonSuite}
return s
}
// NewSuiteG1 returns a G1 suite.
func NewSuiteG1() *Suite {
s := NewSuite()
s.commonSuite.Group = &groupG1{commonSuite: &commonSuite{}}
return s
}
// NewSuiteG2 returns a G2 suite.
func NewSuiteG2() *Suite {
s := NewSuite()
s.commonSuite.Group = &groupG2{commonSuite: &commonSuite{}}
return s
}
// NewSuiteGT returns a GT suite.
func NewSuiteGT() *Suite {
s := NewSuite()
s.commonSuite.Group = &groupGT{commonSuite: &commonSuite{}}
return s
}
// NewSuiteRand generates and returns a new BN254 suite seeded by the
// given cipher stream.
func NewSuiteRand(rand cipher.Stream) *Suite {
s := &Suite{commonSuite: &commonSuite{s: rand}}
s.g1 = &groupG1{
commonSuite: s.commonSuite,
dst: newDefaultDomainG1(),
}
s.g2 = &groupG2{
commonSuite: s.commonSuite,
dst: newDefaultDomainG2(),
}
s.gt = &groupGT{commonSuite: s.commonSuite}
return s
}
// Set G1 DST
func (s *Suite) SetDomainG1(dst []byte) {
newDST := make([]byte, len(dst))
copy(newDST, dst)
s.g1.dst = newDST
}
// Set G2 DST
func (s *Suite) SetDomainG2(dst []byte) {
newDST := make([]byte, len(dst))
copy(newDST, dst)
s.g2.dst = newDST
}
// G1 returns the group G1 of the BN254 pairing.
func (s *Suite) G1() kyber.Group {
return s.g1
}
// G2 returns the group G2 of the BN254 pairing.
func (s *Suite) G2() kyber.Group {
return s.g2
}
// GT returns the group GT of the BN254 pairing.
func (s *Suite) GT() kyber.Group {
return s.gt
}
// Pair takes the points p1 and p2 in groups G1 and G2, respectively, as input
// and computes their pairing in GT.
func (s *Suite) Pair(p1 kyber.Point, p2 kyber.Point) kyber.Point {
return s.GT().Point().(*pointGT).Pair(p1, p2)
}
// NB: Not safe for concurrent calls
func (s *Suite) ValidatePairing(p1, p2, inv1, inv2 kyber.Point) bool {
p2Norm := p2.Clone()
inv2Norm := inv2.Clone()
p2Norm.(*pointG2).g.MakeAffine()
inv2Norm.(*pointG2).g.MakeAffine()
return s.Pair(p1, p2Norm).Equal(s.Pair(inv1, inv2Norm))
}
// Not used other than for reflect.TypeOf()
var aScalar kyber.Scalar
var aPoint kyber.Point
var aPointG1 pointG1
var aPointG2 pointG2
var aPointGT pointGT
var tScalar = reflect.TypeOf(&aScalar).Elem()
var tPoint = reflect.TypeOf(&aPoint).Elem()
var tPointG1 = reflect.TypeOf(&aPointG1).Elem()
var tPointG2 = reflect.TypeOf(&aPointG2).Elem()
var tPointGT = reflect.TypeOf(&aPointGT).Elem()
type commonSuite struct {
s cipher.Stream
// kyber.Group is only set if we have a combined Suite
kyber.Group
}
// New implements the kyber.Encoding interface.
func (c *commonSuite) New(t reflect.Type) interface{} {
if c.Group == nil {
panic("cannot create Point from NewGroup - please use bn254.NewGroupG1")
}
switch t {
case tScalar:
return c.Scalar()
case tPoint:
return c.Point()
case tPointG1:
g1 := groupG1{}
return g1.Point()
case tPointG2:
g2 := groupG2{}
return g2.Point()
case tPointGT:
gt := groupGT{}
return gt.Point()
}
return nil
}
// Read is the default implementation of kyber.Encoding interface Read.
func (c *commonSuite) Read(r io.Reader, objs ...interface{}) error {
return fixbuf.Read(r, c, objs...)
}
// Write is the default implementation of kyber.Encoding interface Write.
func (c *commonSuite) Write(w io.Writer, objs ...interface{}) error {
return fixbuf.Write(w, objs)
}
// Hash returns a newly instantiated keccak256 hash function.
func (c *commonSuite) Hash() hash.Hash {
return sha3.NewLegacyKeccak256()
}
// XOF returns a newlly instantiated blake2xb XOF function.
func (c *commonSuite) XOF(seed []byte) kyber.XOF {
return blake2xb.New(seed)
}
// RandomStream returns a cipher.Stream which corresponds to a key stream from
// crypto/rand.
func (c *commonSuite) RandomStream() cipher.Stream {
if c.s != nil {
return c.s
}
return random.New()
}
// String returns a recognizable string that this is a combined suite.
func (c commonSuite) String() string {
if c.Group != nil {
return c.Group.String()
}
return "bn254"
}