-
Notifications
You must be signed in to change notification settings - Fork 6
/
kyber_g1.go
172 lines (144 loc) · 4.08 KB
/
kyber_g1.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
package bls
import (
"bytes"
"crypto/cipher"
"encoding/hex"
"io"
"github.com/drand/kyber"
"github.com/drand/kyber/group/mod"
bls12381 "github.com/kilic/bls12-381"
)
// domainG1 is the DST used for hash to curve on G1, this is the default from the RFC.
var domainG1 = []byte("BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_")
func DefaultDomainG1() []byte {
return domainG1
}
// KyberG1 is a kyber.Point holding a G1 point on BLS12-381 curve
type KyberG1 struct {
p *bls12381.PointG1
// domain separation tag. We treat a 0 len dst as the default value as per the RFC "Tags MUST have nonzero length"
dst []byte
kyber.Point
kyber.HashablePoint
}
func NullKyberG1(dst ...byte) *KyberG1 {
var p bls12381.PointG1
return newKyberG1(&p, dst)
}
func newKyberG1(p *bls12381.PointG1, dst []byte) *KyberG1 {
domain := dst
if bytes.Equal(dst, domainG1) {
domain = nil
}
return &KyberG1{p: p, dst: domain}
}
func (k *KyberG1) Equal(k2 kyber.Point) bool {
k2g1, ok := k2.(*KyberG1)
if !ok {
return false
}
return bls12381.NewG1().Equal(k.p, k2g1.p) && bytes.Equal(k.dst, k2g1.dst)
}
func (k *KyberG1) Null() kyber.Point {
return newKyberG1(bls12381.NewG1().Zero(), k.dst)
}
func (k *KyberG1) Base() kyber.Point {
return newKyberG1(bls12381.NewG1().One(), k.dst)
}
func (k *KyberG1) Pick(rand cipher.Stream) kyber.Point {
var dst, src [32]byte
rand.XORKeyStream(dst[:], src[:])
return k.Hash(dst[:])
}
func (k *KyberG1) Set(q kyber.Point) kyber.Point {
k.p.Set(q.(*KyberG1).p)
return k
}
func (k *KyberG1) Clone() kyber.Point {
var p bls12381.PointG1
p.Set(k.p)
return newKyberG1(&p, k.dst)
}
func (k *KyberG1) EmbedLen() int {
panic("bls12-381: unsupported operation")
}
func (k *KyberG1) Embed(data []byte, rand cipher.Stream) kyber.Point {
panic("bls12-381: unsupported operation")
}
func (k *KyberG1) Data() ([]byte, error) {
panic("bls12-381: unsupported operation")
}
func (k *KyberG1) Add(a, b kyber.Point) kyber.Point {
aa := a.(*KyberG1)
bb := b.(*KyberG1)
bls12381.NewG1().Add(k.p, aa.p, bb.p)
return k
}
func (k *KyberG1) Sub(a, b kyber.Point) kyber.Point {
aa := a.(*KyberG1)
bb := b.(*KyberG1)
bls12381.NewG1().Sub(k.p, aa.p, bb.p)
return k
}
func (k *KyberG1) Neg(a kyber.Point) kyber.Point {
aa := a.(*KyberG1)
bls12381.NewG1().Neg(k.p, aa.p)
return k
}
func (k *KyberG1) Mul(s kyber.Scalar, q kyber.Point) kyber.Point {
if q == nil {
q = NullKyberG1(k.dst...).Base()
}
bls12381.NewG1().MulScalarBig(k.p, q.(*KyberG1).p, &s.(*mod.Int).V)
return k
}
// MarshalBinary returns a compressed point, without any domain separation tag information
func (k *KyberG1) MarshalBinary() ([]byte, error) {
// we need to clone the point because of https://github.com/kilic/bls12-381/issues/37
// in order to avoid risks of race conditions.
t := new(bls12381.PointG1).Set(k.p)
return bls12381.NewG1().ToCompressed(t), nil
}
// UnmarshalBinary populates the point from a compressed point representation.
func (k *KyberG1) UnmarshalBinary(buff []byte) error {
var err error
k.p, err = bls12381.NewG1().FromCompressed(buff)
return err
}
// MarshalTo writes a compressed point to the Writer, without any domain separation tag information
func (k *KyberG1) MarshalTo(w io.Writer) (int, error) {
buf, err := k.MarshalBinary()
if err != nil {
return 0, err
}
return w.Write(buf)
}
// UnmarshalFrom populates the point from a compressed point representation read from the Reader.
func (k *KyberG1) UnmarshalFrom(r io.Reader) (int, error) {
buf := make([]byte, k.MarshalSize())
n, err := io.ReadFull(r, buf)
if err != nil {
return n, err
}
return n, k.UnmarshalBinary(buf)
}
func (k *KyberG1) MarshalSize() int {
return 48
}
func (k *KyberG1) String() string {
b, _ := k.MarshalBinary()
return "bls12-381.G1: " + hex.EncodeToString(b)
}
func (k *KyberG1) Hash(m []byte) kyber.Point {
domain := domainG1
// We treat a 0 len dst as the default value as per the RFC "Tags MUST have nonzero length"
if len(k.dst) != 0 {
domain = k.dst
}
p, _ := bls12381.NewG1().HashToCurve(m, domain)
k.p = p
return k
}
func (k *KyberG1) IsInCorrectGroup() bool {
return bls12381.NewG1().InCorrectSubgroup(k.p)
}