github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/crypto/secp256k1/secp256.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package secp256k1
    18  
    19  // TODO: set USE_SCALAR_4X64 depending on platform?
    20  
    21  /*
    22  #cgo CFLAGS: -I./libsecp256k1
    23  #cgo CFLAGS: -I./libsecp256k1/src/
    24  #define USE_NUM_NONE
    25  #define USE_FIELD_10X26
    26  #define USE_FIELD_INV_BUILTIN
    27  #define USE_SCALAR_8X32
    28  #define USE_SCALAR_INV_BUILTIN
    29  #define NDEBUG
    30  #include "./libsecp256k1/src/secp256k1.c"
    31  #include "./libsecp256k1/src/modules/recovery/main_impl.h"
    32  #include "pubkey_scalar_mul.h"
    33  
    34  typedef void (*callbackFunc) (const char* msg, void* data);
    35  extern void secp256k1GoPanicIllegal(const char* msg, void* data);
    36  extern void secp256k1GoPanicError(const char* msg, void* data);
    37  */
    38  import "C"
    39  
    40  import (
    41  	"errors"
    42  	"math/big"
    43  	"unsafe"
    44  
    45  	"github.com/ethereumproject/go-ethereum/crypto/randentropy"
    46  )
    47  
    48  //#define USE_FIELD_5X64
    49  
    50  /*
    51     TODO:
    52     > store private keys in buffer and shuffle (deters persistance on swap disc)
    53     > byte permutation (changing)
    54     > xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?)
    55  */
    56  
    57  // holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
    58  var (
    59  	context *C.secp256k1_context
    60  	N       *big.Int
    61  	HalfN   *big.Int
    62  )
    63  
    64  func init() {
    65  	N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
    66  	// N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168
    67  	HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16)
    68  
    69  	// around 20 ms on a modern CPU.
    70  	context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
    71  	C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
    72  	C.secp256k1_context_set_error_callback(context, C.callbackFunc(C.secp256k1GoPanicError), nil)
    73  }
    74  
    75  var (
    76  	ErrInvalidMsgLen       = errors.New("invalid message length for signature recovery")
    77  	ErrInvalidSignatureLen = errors.New("invalid signature length")
    78  	ErrInvalidRecoveryID   = errors.New("invalid signature recovery id")
    79  	ErrInvalidKey          = errors.New("invalid private key")
    80  	ErrInvalidPubkey       = errors.New("invalid public key")
    81  	ErrSignFailed          = errors.New("signing failed")
    82  	ErrRecoverFailed       = errors.New("recovery failed")
    83  )
    84  
    85  func GenerateKeyPair() ([]byte, []byte) {
    86  	var seckey []byte = randentropy.GetEntropyCSPRNG(32)
    87  	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
    88  	var pubkey64 []byte = make([]byte, 64) // secp256k1_pubkey
    89  	var pubkey65 []byte = make([]byte, 65) // 65 byte uncompressed pubkey
    90  	pubkey64_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey64[0]))
    91  	pubkey65_ptr := (*C.uchar)(unsafe.Pointer(&pubkey65[0]))
    92  
    93  	ret := C.secp256k1_ec_pubkey_create(
    94  		context,
    95  		pubkey64_ptr,
    96  		seckey_ptr,
    97  	)
    98  
    99  	if ret != C.int(1) {
   100  		return GenerateKeyPair() // invalid secret, try again
   101  	}
   102  
   103  	var output_len C.size_t
   104  
   105  	C.secp256k1_ec_pubkey_serialize( // always returns 1
   106  		context,
   107  		pubkey65_ptr,
   108  		&output_len,
   109  		pubkey64_ptr,
   110  		0, // SECP256K1_EC_COMPRESSED
   111  	)
   112  
   113  	return pubkey65, seckey
   114  }
   115  
   116  func GeneratePubKey(seckey []byte) ([]byte, error) {
   117  	if err := VerifySeckeyValidity(seckey); err != nil {
   118  		return nil, err
   119  	}
   120  
   121  	var pubkey []byte = make([]byte, 64)
   122  	var pubkey_ptr *C.secp256k1_pubkey = (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0]))
   123  
   124  	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
   125  
   126  	ret := C.secp256k1_ec_pubkey_create(
   127  		context,
   128  		pubkey_ptr,
   129  		seckey_ptr,
   130  	)
   131  
   132  	if ret != C.int(1) {
   133  		return nil, errors.New("Unable to generate pubkey from seckey")
   134  	}
   135  
   136  	return pubkey, nil
   137  }
   138  
   139  // SignNondeterministic generates nondeterministic signature b/c of a random k-value in the ECDSA algorithm. This function is included
   140  // only for purpose of demonstration and comparison with the deterministic Sign function.
   141  func SignNondeterministic(msg []byte, seckey []byte) ([]byte, error) {
   142  	msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0]))
   143  	seckey_ptr := (*C.uchar)(unsafe.Pointer(&seckey[0]))
   144  
   145  	sig := make([]byte, 65)
   146  	sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&sig[0]))
   147  
   148  	nonce := randentropy.GetEntropyCSPRNG(32)
   149  	ndata_ptr := unsafe.Pointer(&nonce[0])
   150  
   151  	noncefp_ptr := &(*C.secp256k1_nonce_function_default)
   152  
   153  	if C.secp256k1_ec_seckey_verify(context, seckey_ptr) != C.int(1) {
   154  		return nil, errors.New("Invalid secret key")
   155  	}
   156  
   157  	ret := C.secp256k1_ecdsa_sign_recoverable(
   158  		context,
   159  		sig_ptr,
   160  		msg_ptr,
   161  		seckey_ptr,
   162  		noncefp_ptr,
   163  		ndata_ptr,
   164  	)
   165  
   166  	if ret == C.int(0) {
   167  		return Sign(msg, seckey) //invalid secret, try again
   168  	}
   169  
   170  	sig_serialized := make([]byte, 65)
   171  	sig_serialized_ptr := (*C.uchar)(unsafe.Pointer(&sig_serialized[0]))
   172  	var recid C.int
   173  
   174  	C.secp256k1_ecdsa_recoverable_signature_serialize_compact(
   175  		context,
   176  		sig_serialized_ptr, // 64 byte compact signature
   177  		&recid,
   178  		sig_ptr, // 65 byte "recoverable" signature
   179  	)
   180  
   181  	sig_serialized[64] = byte(int(recid)) // add back recid to get 65 bytes sig
   182  
   183  	return sig_serialized, nil
   184  
   185  }
   186  
   187  // Sign creates a recoverable ECDSA signature.
   188  // The produced signature is in the 65-byte [R || S || V] format where V is 0 or 1.
   189  //
   190  // The caller is responsible for ensuring that msg cannot be chosen
   191  // directly by an attacker. It is usually preferable to use a cryptographic
   192  // hash function on any input before handing it to this function.
   193  func Sign(msg []byte, seckey []byte) ([]byte, error) {
   194  	if len(msg) != 32 {
   195  		return nil, ErrInvalidMsgLen
   196  	}
   197  	if len(seckey) != 32 {
   198  		return nil, ErrInvalidKey
   199  	}
   200  	seckeydata := (*C.uchar)(unsafe.Pointer(&seckey[0]))
   201  	if C.secp256k1_ec_seckey_verify(context, seckeydata) != 1 {
   202  		return nil, ErrInvalidKey
   203  	}
   204  
   205  	var (
   206  		msgdata   = (*C.uchar)(unsafe.Pointer(&msg[0]))
   207  		noncefunc = C.secp256k1_nonce_function_rfc6979
   208  		sigstruct C.secp256k1_ecdsa_recoverable_signature
   209  	)
   210  	if C.secp256k1_ecdsa_sign_recoverable(context, &sigstruct, msgdata, seckeydata, noncefunc, nil) == 0 {
   211  		return nil, ErrSignFailed
   212  	}
   213  
   214  	var (
   215  		sig     = make([]byte, 65)
   216  		sigdata = (*C.uchar)(unsafe.Pointer(&sig[0]))
   217  		recid   C.int
   218  	)
   219  	C.secp256k1_ecdsa_recoverable_signature_serialize_compact(context, sigdata, &recid, &sigstruct)
   220  	sig[64] = byte(recid) // add back recid to get 65 bytes sig
   221  	return sig, nil
   222  }
   223  
   224  func VerifySeckeyValidity(seckey []byte) error {
   225  	if len(seckey) != 32 {
   226  		return errors.New("priv key is not 32 bytes")
   227  	}
   228  	var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
   229  	ret := C.secp256k1_ec_seckey_verify(context, seckey_ptr)
   230  	if int(ret) != 1 {
   231  		return errors.New("invalid seckey")
   232  	}
   233  	return nil
   234  }
   235  
   236  // RecoverPubkey returns the the public key of the signer.
   237  // msg must be the 32-byte hash of the message to be signed.
   238  // sig must be a 65-byte compact ECDSA signature containing the
   239  // recovery id as the last element.
   240  func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
   241  	if len(msg) != 32 {
   242  		return nil, ErrInvalidMsgLen
   243  	}
   244  	if err := checkSignature(sig); err != nil {
   245  		return nil, err
   246  	}
   247  
   248  	msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0]))
   249  	sig_ptr := (*C.uchar)(unsafe.Pointer(&sig[0]))
   250  	pubkey := make([]byte, 64)
   251  	/*
   252  		this slice is used for both the recoverable signature and the
   253  		resulting serialized pubkey (both types in libsecp256k1 are 65
   254  		bytes). this saves one allocation of 65 bytes, which is nice as
   255  		pubkey recovery is one bottleneck during load in Ethereum
   256  	*/
   257  	bytes65 := make([]byte, 65)
   258  	pubkey_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0]))
   259  	recoverable_sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&bytes65[0]))
   260  	recid := C.int(sig[64])
   261  
   262  	ret := C.secp256k1_ecdsa_recoverable_signature_parse_compact(
   263  		context,
   264  		recoverable_sig_ptr,
   265  		sig_ptr,
   266  		recid)
   267  	if ret == C.int(0) {
   268  		return nil, errors.New("Failed to parse signature")
   269  	}
   270  
   271  	ret = C.secp256k1_ecdsa_recover(
   272  		context,
   273  		pubkey_ptr,
   274  		recoverable_sig_ptr,
   275  		msg_ptr,
   276  	)
   277  	if ret == C.int(0) {
   278  		return nil, errors.New("Failed to recover public key")
   279  	}
   280  
   281  	serialized_pubkey_ptr := (*C.uchar)(unsafe.Pointer(&bytes65[0]))
   282  	var output_len C.size_t
   283  	C.secp256k1_ec_pubkey_serialize( // always returns 1
   284  		context,
   285  		serialized_pubkey_ptr,
   286  		&output_len,
   287  		pubkey_ptr,
   288  		0, // SECP256K1_EC_COMPRESSED
   289  	)
   290  	return bytes65, nil
   291  }
   292  
   293  func checkSignature(sig []byte) error {
   294  	if len(sig) != 65 {
   295  		return ErrInvalidSignatureLen
   296  	}
   297  	if sig[64] >= 4 {
   298  		return ErrInvalidRecoveryID
   299  	}
   300  	return nil
   301  }
   302  
   303  // reads num into buf as big-endian bytes.
   304  func readBits(buf []byte, num *big.Int) {
   305  	const wordLen = int(unsafe.Sizeof(big.Word(0)))
   306  	i := len(buf)
   307  	for _, d := range num.Bits() {
   308  		for j := 0; j < wordLen && i > 0; j++ {
   309  			i--
   310  			buf[i] = byte(d)
   311  			d >>= 8
   312  		}
   313  	}
   314  }