| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | package secp256k1 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | // TODO: set USE_SCALAR_4X64 depending on platform? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | #cgo CFLAGS: -I./libsecp256k1 | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | #cgo CFLAGS: -I./libsecp256k1/src/ | 
					
						
							| 
									
										
										
										
											2015-12-03 20:04:39 +01:00
										 |  |  | #define USE_NUM_NONE | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | #define USE_FIELD_10X26 | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | #define USE_FIELD_INV_BUILTIN | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | #define USE_SCALAR_8X32 | 
					
						
							|  |  |  | #define USE_SCALAR_INV_BUILTIN | 
					
						
							| 
									
										
										
										
											2015-04-07 18:09:58 +02:00
										 |  |  | #define NDEBUG | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | #include "./libsecp256k1/src/secp256k1.c" | 
					
						
							|  |  |  | #include "./libsecp256k1/src/modules/recovery/main_impl.h" | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | #include "pubkey_scalar_mul.h" | 
					
						
							| 
									
										
										
										
											2015-11-16 18:04:56 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef void (*callbackFunc) (const char* msg, void* data); | 
					
						
							|  |  |  | extern void secp256k1GoPanicIllegal(const char* msg, void* data); | 
					
						
							|  |  |  | extern void secp256k1GoPanicError(const char* msg, void* data); | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | */ | 
					
						
							|  |  |  | import "C" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	"unsafe" | 
					
						
							| 
									
										
										
										
											2015-02-15 02:20:31 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/crypto/randentropy" | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //#define USE_FIELD_5X64 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  |    TODO: | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  |    > store private keys in buffer and shuffle (deters persistance on swap disc) | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  |    > byte permutation (changing) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  |    > xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?) | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | // holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h) | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	context *C.secp256k1_context | 
					
						
							|  |  |  | 	N       *big.Int | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	HalfN   *big.Int | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | func init() { | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | 	N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16) | 
					
						
							| 
									
										
										
										
											2015-11-27 15:40:29 +01:00
										 |  |  | 	// N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168 | 
					
						
							|  |  |  | 	HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	// around 20 ms on a modern CPU. | 
					
						
							|  |  |  | 	context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY | 
					
						
							| 
									
										
										
										
											2015-11-16 18:04:56 +01:00
										 |  |  | 	C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil) | 
					
						
							|  |  |  | 	C.secp256k1_context_set_error_callback(context, C.callbackFunc(C.secp256k1GoPanicError), nil) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-16 17:11:26 +01:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	ErrInvalidMsgLen       = errors.New("invalid message length for signature recovery") | 
					
						
							|  |  |  | 	ErrInvalidSignatureLen = errors.New("invalid signature length") | 
					
						
							|  |  |  | 	ErrInvalidRecoveryID   = errors.New("invalid signature recovery id") | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | func GenerateKeyPair() ([]byte, []byte) { | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	var seckey []byte = randentropy.GetEntropyCSPRNG(32) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	var pubkey64 []byte = make([]byte, 64) // secp256k1_pubkey | 
					
						
							|  |  |  | 	var pubkey65 []byte = make([]byte, 65) // 65 byte uncompressed pubkey | 
					
						
							|  |  |  | 	pubkey64_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey64[0])) | 
					
						
							|  |  |  | 	pubkey65_ptr := (*C.uchar)(unsafe.Pointer(&pubkey65[0])) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | 	ret := C.secp256k1_ec_pubkey_create( | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		context, | 
					
						
							|  |  |  | 		pubkey64_ptr, | 
					
						
							|  |  |  | 		seckey_ptr, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ret != C.int(1) { | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		return GenerateKeyPair() // invalid secret, try again | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var output_len C.size_t | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | 	C.secp256k1_ec_pubkey_serialize( // always returns 1 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		context, | 
					
						
							|  |  |  | 		pubkey65_ptr, | 
					
						
							|  |  |  | 		&output_len, | 
					
						
							|  |  |  | 		pubkey64_ptr, | 
					
						
							|  |  |  | 		0, // SECP256K1_EC_COMPRESSED | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return pubkey65, seckey | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func GeneratePubKey(seckey []byte) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2015-02-15 02:20:31 +01:00
										 |  |  | 	if err := VerifySeckeyValidity(seckey); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	var pubkey []byte = make([]byte, 64) | 
					
						
							|  |  |  | 	var pubkey_ptr *C.secp256k1_pubkey = (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0])) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | 	ret := C.secp256k1_ec_pubkey_create( | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		context, | 
					
						
							|  |  |  | 		pubkey_ptr, | 
					
						
							|  |  |  | 		seckey_ptr, | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if ret != C.int(1) { | 
					
						
							|  |  |  | 		return nil, errors.New("Unable to generate pubkey from seckey") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return pubkey, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func Sign(msg []byte, seckey []byte) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0])) | 
					
						
							|  |  |  | 	seckey_ptr := (*C.uchar)(unsafe.Pointer(&seckey[0])) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	sig := make([]byte, 65) | 
					
						
							|  |  |  | 	sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&sig[0])) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	nonce := randentropy.GetEntropyCSPRNG(32) | 
					
						
							|  |  |  | 	ndata_ptr := unsafe.Pointer(&nonce[0]) | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	noncefp_ptr := &(*C.secp256k1_nonce_function_default) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	if C.secp256k1_ec_seckey_verify(context, seckey_ptr) != C.int(1) { | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 		return nil, errors.New("Invalid secret key") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	ret := C.secp256k1_ecdsa_sign_recoverable( | 
					
						
							|  |  |  | 		context, | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 		sig_ptr, | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		msg_ptr, | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 		seckey_ptr, | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | 		noncefp_ptr, | 
					
						
							|  |  |  | 		ndata_ptr, | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	if ret == C.int(0) { | 
					
						
							|  |  |  | 		return Sign(msg, seckey) //invalid secret, try again | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	sig_serialized := make([]byte, 65) | 
					
						
							|  |  |  | 	sig_serialized_ptr := (*C.uchar)(unsafe.Pointer(&sig_serialized[0])) | 
					
						
							|  |  |  | 	var recid C.int | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | 	C.secp256k1_ecdsa_recoverable_signature_serialize_compact( | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		context, | 
					
						
							|  |  |  | 		sig_serialized_ptr, // 64 byte compact signature | 
					
						
							|  |  |  | 		&recid, | 
					
						
							|  |  |  | 		sig_ptr, // 65 byte "recoverable" signature | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sig_serialized[64] = byte(int(recid)) // add back recid to get 65 bytes sig | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sig_serialized, nil | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func VerifySeckeyValidity(seckey []byte) error { | 
					
						
							|  |  |  | 	if len(seckey) != 32 { | 
					
						
							|  |  |  | 		return errors.New("priv key is not 32 bytes") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0])) | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	ret := C.secp256k1_ec_seckey_verify(context, seckey_ptr) | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	if int(ret) != 1 { | 
					
						
							|  |  |  | 		return errors.New("invalid seckey") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-16 17:11:26 +01:00
										 |  |  | // RecoverPubkey returns the the public key of the signer. | 
					
						
							|  |  |  | // msg must be the 32-byte hash of the message to be signed. | 
					
						
							|  |  |  | // sig must be a 65-byte compact ECDSA signature containing the | 
					
						
							|  |  |  | // recovery id as the last element. | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2015-11-16 17:11:26 +01:00
										 |  |  | 	if len(msg) != 32 { | 
					
						
							|  |  |  | 		return nil, ErrInvalidMsgLen | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := checkSignature(sig); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0])) | 
					
						
							|  |  |  | 	sig_ptr := (*C.uchar)(unsafe.Pointer(&sig[0])) | 
					
						
							|  |  |  | 	pubkey := make([]byte, 64) | 
					
						
							|  |  |  | 	/* | 
					
						
							|  |  |  | 		this slice is used for both the recoverable signature and the | 
					
						
							|  |  |  | 		resulting serialized pubkey (both types in libsecp256k1 are 65 | 
					
						
							|  |  |  | 		bytes). this saves one allocation of 65 bytes, which is nice as | 
					
						
							|  |  |  | 		pubkey recovery is one bottleneck during load in Ethereum | 
					
						
							|  |  |  | 	*/ | 
					
						
							|  |  |  | 	bytes65 := make([]byte, 65) | 
					
						
							|  |  |  | 	pubkey_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0])) | 
					
						
							|  |  |  | 	recoverable_sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&bytes65[0])) | 
					
						
							|  |  |  | 	recid := C.int(sig[64]) | 
					
						
							| 
									
										
										
										
											2015-11-16 17:11:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	ret := C.secp256k1_ecdsa_recoverable_signature_parse_compact( | 
					
						
							|  |  |  | 		context, | 
					
						
							|  |  |  | 		recoverable_sig_ptr, | 
					
						
							|  |  |  | 		sig_ptr, | 
					
						
							|  |  |  | 		recid) | 
					
						
							|  |  |  | 	if ret == C.int(0) { | 
					
						
							|  |  |  | 		return nil, errors.New("Failed to parse signature") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 	ret = C.secp256k1_ecdsa_recover( | 
					
						
							|  |  |  | 		context, | 
					
						
							| 
									
										
										
										
											2015-04-07 12:40:31 +02:00
										 |  |  | 		pubkey_ptr, | 
					
						
							| 
									
										
										
										
											2015-09-28 11:19:23 +02:00
										 |  |  | 		recoverable_sig_ptr, | 
					
						
							|  |  |  | 		msg_ptr, | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	if ret == C.int(0) { | 
					
						
							|  |  |  | 		return nil, errors.New("Failed to recover public key") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-11-16 17:11:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	serialized_pubkey_ptr := (*C.uchar)(unsafe.Pointer(&bytes65[0])) | 
					
						
							|  |  |  | 	var output_len C.size_t | 
					
						
							|  |  |  | 	C.secp256k1_ec_pubkey_serialize( // always returns 1 | 
					
						
							|  |  |  | 		context, | 
					
						
							|  |  |  | 		serialized_pubkey_ptr, | 
					
						
							|  |  |  | 		&output_len, | 
					
						
							|  |  |  | 		pubkey_ptr, | 
					
						
							|  |  |  | 		0, // SECP256K1_EC_COMPRESSED | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	return bytes65, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func checkSignature(sig []byte) error { | 
					
						
							|  |  |  | 	if len(sig) != 65 { | 
					
						
							|  |  |  | 		return ErrInvalidSignatureLen | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if sig[64] >= 4 { | 
					
						
							|  |  |  | 		return ErrInvalidRecoveryID | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							| 
									
										
										
										
											2015-01-22 00:35:00 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-09-29 19:37:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | // reads num into buf as big-endian bytes. | 
					
						
							|  |  |  | func readBits(buf []byte, num *big.Int) { | 
					
						
							|  |  |  | 	const wordLen = int(unsafe.Sizeof(big.Word(0))) | 
					
						
							|  |  |  | 	i := len(buf) | 
					
						
							|  |  |  | 	for _, d := range num.Bits() { | 
					
						
							|  |  |  | 		for j := 0; j < wordLen && i > 0; j++ { | 
					
						
							|  |  |  | 			i-- | 
					
						
							|  |  |  | 			buf[i] = byte(d) | 
					
						
							|  |  |  | 			d >>= 8 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |