@@ -39,7 +39,6 @@ package secp256k1
39
39
import "C"
40
40
41
41
import (
42
- "bytes"
43
42
"errors"
44
43
"unsafe"
45
44
@@ -64,6 +63,12 @@ func init() {
64
63
context = C .secp256k1_context_create (3 ) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
65
64
}
66
65
66
+ var (
67
+ ErrInvalidMsgLen = errors .New ("invalid message length for signature recovery" )
68
+ ErrInvalidSignatureLen = errors .New ("invalid signature length" )
69
+ ErrInvalidRecoveryID = errors .New ("invalid signature recovery id" )
70
+ )
71
+
67
72
func GenerateKeyPair () ([]byte , []byte ) {
68
73
var seckey []byte = randentropy .GetEntropyCSPRNG (32 )
69
74
var seckey_ptr * C.uchar = (* C .uchar )(unsafe .Pointer (& seckey [0 ]))
@@ -177,69 +182,20 @@ func VerifySeckeyValidity(seckey []byte) error {
177
182
return nil
178
183
}
179
184
180
- func VerifySignatureValidity (sig []byte ) bool {
181
- //64+1
182
- if len (sig ) != 65 {
183
- return false
184
- }
185
- //malleability check, highest bit must be 1
186
- if (sig [32 ] & 0x80 ) == 0x80 {
187
- return false
188
- }
189
- //recovery id check
190
- if sig [64 ] >= 4 {
191
- return false
192
- }
193
-
194
- return true
195
- }
196
-
197
- //for compressed signatures, does not need pubkey
198
- func VerifySignature (msg []byte , sig []byte , pubkey1 []byte ) error {
199
- if msg == nil || sig == nil || pubkey1 == nil {
200
- return errors .New ("inputs must be non-nil" )
201
- }
202
- if len (sig ) != 65 {
203
- return errors .New ("invalid signature length" )
204
- }
205
- if len (pubkey1 ) != 65 {
206
- return errors .New ("Invalid public key length" )
207
- }
208
-
209
- //to enforce malleability, highest bit of S must be 0
210
- //S starts at 32nd byte
211
- if (sig [32 ] & 0x80 ) == 0x80 { //highest bit must be 1
212
- return errors .New ("Signature not malleable" )
213
- }
214
-
215
- if sig [64 ] >= 4 {
216
- return errors .New ("Recover byte invalid" )
217
- }
218
-
219
- // if pubkey recovered, signature valid
220
- pubkey2 , err := RecoverPubkey (msg , sig )
221
- if err != nil {
222
- return err
223
- }
224
- if len (pubkey2 ) != 65 {
225
- return errors .New ("Invalid recovered public key length" )
226
- }
227
- if ! bytes .Equal (pubkey1 , pubkey2 ) {
228
- return errors .New ("Public key does not match recovered public key" )
229
- }
230
-
231
- return nil
232
- }
233
-
234
- // recovers a public key from the signature
185
+ // RecoverPubkey returns the the public key of the signer.
186
+ // msg must be the 32-byte hash of the message to be signed.
187
+ // sig must be a 65-byte compact ECDSA signature containing the
188
+ // recovery id as the last element.
235
189
func RecoverPubkey (msg []byte , sig []byte ) ([]byte , error ) {
236
- if len (sig ) != 65 {
237
- return nil , errors .New ("Invalid signature length" )
190
+ if len (msg ) != 32 {
191
+ return nil , ErrInvalidMsgLen
192
+ }
193
+ if err := checkSignature (sig ); err != nil {
194
+ return nil , err
238
195
}
239
196
240
197
msg_ptr := (* C .uchar )(unsafe .Pointer (& msg [0 ]))
241
198
sig_ptr := (* C .uchar )(unsafe .Pointer (& sig [0 ]))
242
-
243
199
pubkey := make ([]byte , 64 )
244
200
/*
245
201
this slice is used for both the recoverable signature and the
@@ -248,17 +204,15 @@ func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
248
204
pubkey recovery is one bottleneck during load in Ethereum
249
205
*/
250
206
bytes65 := make ([]byte , 65 )
251
-
252
207
pubkey_ptr := (* C .secp256k1_pubkey )(unsafe .Pointer (& pubkey [0 ]))
253
208
recoverable_sig_ptr := (* C .secp256k1_ecdsa_recoverable_signature )(unsafe .Pointer (& bytes65 [0 ]))
254
-
255
209
recid := C .int (sig [64 ])
210
+
256
211
ret := C .secp256k1_ecdsa_recoverable_signature_parse_compact (
257
212
context ,
258
213
recoverable_sig_ptr ,
259
214
sig_ptr ,
260
215
recid )
261
-
262
216
if ret == C .int (0 ) {
263
217
return nil , errors .New ("Failed to parse signature" )
264
218
}
@@ -269,20 +223,28 @@ func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
269
223
recoverable_sig_ptr ,
270
224
msg_ptr ,
271
225
)
272
-
273
226
if ret == C .int (0 ) {
274
227
return nil , errors .New ("Failed to recover public key" )
275
- } else {
276
- serialized_pubkey_ptr := (* C .uchar )(unsafe .Pointer (& bytes65 [0 ]))
277
-
278
- var output_len C.size_t
279
- C .secp256k1_ec_pubkey_serialize ( // always returns 1
280
- context ,
281
- serialized_pubkey_ptr ,
282
- & output_len ,
283
- pubkey_ptr ,
284
- 0 , // SECP256K1_EC_COMPRESSED
285
- )
286
- return bytes65 , nil
287
228
}
229
+
230
+ serialized_pubkey_ptr := (* C .uchar )(unsafe .Pointer (& bytes65 [0 ]))
231
+ var output_len C.size_t
232
+ C .secp256k1_ec_pubkey_serialize ( // always returns 1
233
+ context ,
234
+ serialized_pubkey_ptr ,
235
+ & output_len ,
236
+ pubkey_ptr ,
237
+ 0 , // SECP256K1_EC_COMPRESSED
238
+ )
239
+ return bytes65 , nil
240
+ }
241
+
242
+ func checkSignature (sig []byte ) error {
243
+ if len (sig ) != 65 {
244
+ return ErrInvalidSignatureLen
245
+ }
246
+ if sig [64 ] >= 4 {
247
+ return ErrInvalidRecoveryID
248
+ }
249
+ return nil
288
250
}
0 commit comments