-
Notifications
You must be signed in to change notification settings - Fork 1
/
generator.go
232 lines (199 loc) · 6.08 KB
/
generator.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
222
223
224
225
226
227
228
229
230
231
232
/*
This package implements Zero Knowledge Proof algorithms for Golang
Contains Go bindings for the secp256k1-zkp C-library, which is
based on the secp256k1 - a highly optimized implementation of the
256-bit elliptic curve used in Bitcoin blockchain.
*/
package secp256k1
/*
#include "include/secp256k1_generator.h"
#cgo CFLAGS: -I${SRCDIR}/secp256k1-zkp -I${SRCDIR}/secp256k1-zkp/src
*/
import "C"
import (
"encoding/hex"
"errors"
)
/******************************************************************************
Pointer to opaque data structure that stores a base point
---------------------------------------------------------
The exact representation of data inside is implementation defined and not
guaranteed to be portable between different platforms or versions. It is
however guaranteed to be 64 bytes in size, and can be safely copied/moved.
If you need to convert to a format suitable for storage, transmission, or
comparison, use secp256k1_generator_serialize and secp256k1_generator_parse.
*******************************************************************************/
type Generator struct {
gen *C.secp256k1_generator
}
const (
ErrorGeneratorParse string = "failed to parse data as a generator"
ErrorGeneratorGenerate string = "failed to create a generator"
)
var (
// Standard secp256k1 generator G
GeneratorG = Generator{&C.secp256k1_generator_const_g}
// Alternate secp256k1 generator from Elements Alpha
GeneratorH = Generator{&C.secp256k1_generator_const_h}
)
type GeneratorHex string
type GeneratorSerialized [33]byte
type GeneratorSerializedSlice []byte
// type GeneratorSerializedSlice = []byte
func newGenerator() *Generator {
return &Generator{
gen: &C.secp256k1_generator{},
}
}
// Parse a 33-byte generator byte sequence into a generator object.
// -> context a secp256k1 context object.
// -> bytes 33-byte slice of data
// <- generator pointer to a generator object
// <- err nil if success or an error object
func GeneratorParse(
context *Context,
bytes []byte,
) (
generator *Generator,
err error,
) {
if LenCompressed != len(bytes) {
return nil, errors.New(ErrorGeneratorParse + " (invalid length)")
}
if context == nil {
context = SharedContext(ContextNone)
}
generator = newGenerator()
if 1 != C.secp256k1_generator_parse(
context.ctx,
generator.gen,
cBuf(bytes)) {
return nil, errors.New(ErrorGeneratorParse)
}
return
}
// Serialize a 33-byte generator into a serialized byte sequence
// -> context non-NULL context
// -> generator generator object
// <- bytes 33 bytes of data
func GeneratorSerialize(
context *Context,
generator *Generator,
) (
bytes [33]byte,
) {
if context == nil {
context = SharedContext(ContextNone)
}
C.secp256k1_generator_serialize(
context.ctx,
cBuf(bytes[:]),
generator.gen)
return
}
// Convert commitment object to array of bytes
func (gen *Generator) Bytes() (bytes [33]byte) {
bytes = GeneratorSerialize(SharedContext(ContextNone), gen)
return
}
func (gen *Generator) String() string {
bytes := gen.Bytes()
return hex.EncodeToString(bytes[:])
}
func GeneratorFromString(str string) (gen *Generator, err error) {
bytes, err := hex.DecodeString(str)
if err != nil {
return
}
gen, err = GeneratorParse(SharedContext(ContextNone), bytes)
return
}
func GeneratorFromBytes(bytes []byte) (gen *Generator, err error) {
gen, err = GeneratorParse(SharedContext(ContextNone), bytes)
return
}
// String method serializes generator as a hex string
// Generator returns object created from serialized data bytes
// Returns nil if failed to parse
func (genser GeneratorSerialized) Generator() (generator *Generator) {
gen, err := GeneratorParse(nil, genser[:])
if err != nil {
generator = gen
}
return
}
func (genser GeneratorSerialized) String() string {
return string(genser[:])
}
func (genserslc GeneratorSerializedSlice) Generator() (generator *Generator) {
var err error
if generator, err = GeneratorParse(nil, genserslc); err == nil {
return nil
}
return
}
func (genhex GeneratorHex) Generator() (generator *Generator) {
str := string(genhex)
if genser, err := hex.DecodeString(str); err == nil {
return nil
} else {
if generator, err = GeneratorParse(nil, []byte(genser)); err == nil {
return nil
}
}
return
}
// Generate a generator for the curve.
//
// Returns: 0 in the highly unlikely case the seed is not acceptable,
// 1 otherwise.
// Args: ctx: a secp256k1 context object
// Out: gen: a generator object
// In: seed32: a 32-byte seed
//
// If successful a valid generator will be placed in gen. The produced
// generators are distributed uniformly over the curve, and will not have a
// known discrete logarithm with respect to any other generator produced,
// or to the base generator G.
//
func GeneratorGenerate(ctx *Context, seed []byte) (*Generator, error) {
if ctx == nil {
ctx = SharedContext(ContextSign)
}
generator := newGenerator()
if 1 != C.secp256k1_generator_generate(
ctx.ctx,
generator.gen,
cBuf(seed)) {
return nil, errors.New(ErrorGeneratorGenerate)
}
return generator, nil
}
// Generate a blinded generator for the curve.
//
// Returns: 0 in the highly unlikely case the seed is not acceptable or when
// blind is out of range. 1 otherwise.
// Args: ctx: a secp256k1 context object, initialized for signing
// Out: gen: a generator object
// In: seed32: a 32-byte seed
// blind32: a 32-byte secret value to blind the genesizeofrator with.
//
// The result is equivalent to first calling secp256k1_gensizeoferator_generate,
// converting the result to a public key, calling secp256k1_ec_pubkey_tweak_add,
// and then converting back to generator form.sizeof
//
func GeneratorGenerateBlinded(ctx *Context, seed []byte, blind []byte) (*Generator, error) {
if ctx == nil {
ctx = SharedContext(ContextSign)
}
generator := newGenerator()
if 1 != int(
C.secp256k1_generator_generate_blinded(
ctx.ctx,
generator.gen,
cBuf(seed),
cBuf(blind))) {
return nil, errors.New(ErrorGeneratorGenerate)
}
return generator, nil
}