github.com/klaytn/klaytn@v1.12.1/crypto/secp256k1/secp256.go (about)

     1  // Copyright 2018 The klaytn Authors
     2  // Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
     3  // Use of this source code is governed by a BSD-style license that can be found in
     4  // the LICENSE file.
     5  //
     6  // This file is derived from crypto/secp256k1/secp256.go (2018/06/04).
     7  // Modified and improved for the klaytn development.
     8  
     9  package secp256k1
    10  
    11  /*
    12  #cgo CFLAGS: -I./libsecp256k1
    13  #cgo CFLAGS: -I./libsecp256k1/src/
    14  
    15  #ifdef __SIZEOF_INT128__
    16  #  define HAVE___INT128
    17  #  define USE_FIELD_5X52
    18  #  define USE_SCALAR_4X64
    19  #else
    20  #  define USE_FIELD_10X26
    21  #  define USE_SCALAR_8X32
    22  #endif
    23  #define USE_ENDOMORPHISM
    24  #define USE_NUM_NONE
    25  #define USE_FIELD_INV_BUILTIN
    26  #define USE_SCALAR_INV_BUILTIN
    27  #define NDEBUG
    28  #include "./libsecp256k1/src/secp256k1.c"
    29  #include "./libsecp256k1/src/modules/recovery/main_impl.h"
    30  #include "ext.h"
    31  
    32  typedef void (*callbackFunc) (const char* msg, void* data);
    33  extern void secp256k1GoPanicIllegal(const char* msg, void* data);
    34  extern void secp256k1GoPanicError(const char* msg, void* data);
    35  */
    36  import "C"
    37  
    38  import (
    39  	"errors"
    40  	"math/big"
    41  	"unsafe"
    42  )
    43  
    44  var context *C.secp256k1_context
    45  
    46  func init() {
    47  	// around 20 ms on a modern CPU.
    48  	context = C.secp256k1_context_create_sign_verify()
    49  	C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
    50  	C.secp256k1_context_set_error_callback(context, C.callbackFunc(C.secp256k1GoPanicError), nil)
    51  }
    52  
    53  var (
    54  	ErrInvalidMsgLen       = errors.New("invalid message length, need 32 bytes")
    55  	ErrInvalidSignatureLen = errors.New("invalid signature length")
    56  	ErrInvalidRecoveryID   = errors.New("invalid signature recovery id")
    57  	ErrInvalidKey          = errors.New("invalid private key")
    58  	ErrInvalidPubkey       = errors.New("invalid public key")
    59  	ErrSignFailed          = errors.New("signing failed")
    60  	ErrRecoverFailed       = errors.New("recovery failed")
    61  )
    62  
    63  // Sign creates a recoverable ECDSA signature.
    64  // The produced signature is in the 65-byte [R || S || V] format where V is 0 or 1.
    65  //
    66  // The caller is responsible for ensuring that msg cannot be chosen
    67  // directly by an attacker. It is usually preferable to use a cryptographic
    68  // hash function on any input before handing it to this function.
    69  func Sign(msg []byte, seckey []byte) ([]byte, error) {
    70  	if len(msg) != 32 {
    71  		return nil, ErrInvalidMsgLen
    72  	}
    73  	if len(seckey) != 32 {
    74  		return nil, ErrInvalidKey
    75  	}
    76  	seckeydata := (*C.uchar)(unsafe.Pointer(&seckey[0]))
    77  	if C.secp256k1_ec_seckey_verify(context, seckeydata) != 1 {
    78  		return nil, ErrInvalidKey
    79  	}
    80  
    81  	var (
    82  		msgdata   = (*C.uchar)(unsafe.Pointer(&msg[0]))
    83  		noncefunc = C.secp256k1_nonce_function_rfc6979
    84  		sigstruct C.secp256k1_ecdsa_recoverable_signature
    85  	)
    86  	if C.secp256k1_ecdsa_sign_recoverable(context, &sigstruct, msgdata, seckeydata, noncefunc, nil) == 0 {
    87  		return nil, ErrSignFailed
    88  	}
    89  
    90  	var (
    91  		sig     = make([]byte, 65)
    92  		sigdata = (*C.uchar)(unsafe.Pointer(&sig[0]))
    93  		recid   C.int
    94  	)
    95  	C.secp256k1_ecdsa_recoverable_signature_serialize_compact(context, sigdata, &recid, &sigstruct)
    96  	sig[64] = byte(recid) // add back recid to get 65 bytes sig
    97  	return sig, nil
    98  }
    99  
   100  // RecoverPubkey returns the public key of the signer.
   101  // msg must be the 32-byte hash of the message to be signed.
   102  // sig must be a 65-byte compact ECDSA signature containing the
   103  // recovery id as the last element.
   104  func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
   105  	if len(msg) != 32 {
   106  		return nil, ErrInvalidMsgLen
   107  	}
   108  	if err := checkSignature(sig); err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	var (
   113  		pubkey  = make([]byte, 65)
   114  		sigdata = (*C.uchar)(unsafe.Pointer(&sig[0]))
   115  		msgdata = (*C.uchar)(unsafe.Pointer(&msg[0]))
   116  	)
   117  	if C.secp256k1_ext_ecdsa_recover(context, (*C.uchar)(unsafe.Pointer(&pubkey[0])), sigdata, msgdata) == 0 {
   118  		return nil, ErrRecoverFailed
   119  	}
   120  	return pubkey, nil
   121  }
   122  
   123  // VerifySignature checks that the given pubkey created signature over message.
   124  // The signature should be in [R || S] format.
   125  func VerifySignature(pubkey, msg, signature []byte) bool {
   126  	if len(msg) != 32 || len(signature) != 64 || len(pubkey) == 0 {
   127  		return false
   128  	}
   129  	sigdata := (*C.uchar)(unsafe.Pointer(&signature[0]))
   130  	msgdata := (*C.uchar)(unsafe.Pointer(&msg[0]))
   131  	keydata := (*C.uchar)(unsafe.Pointer(&pubkey[0]))
   132  	return C.secp256k1_ext_ecdsa_verify(context, sigdata, msgdata, keydata, C.size_t(len(pubkey))) != 0
   133  }
   134  
   135  // DecompressPubkey parses a public key in the 33-byte compressed format.
   136  // It returns non-nil coordinates if the public key is valid.
   137  func DecompressPubkey(pubkey []byte) (x, y *big.Int) {
   138  	if len(pubkey) != 33 {
   139  		return nil, nil
   140  	}
   141  	var (
   142  		pubkeydata = (*C.uchar)(unsafe.Pointer(&pubkey[0]))
   143  		pubkeylen  = C.size_t(len(pubkey))
   144  		out        = make([]byte, 65)
   145  		outdata    = (*C.uchar)(unsafe.Pointer(&out[0]))
   146  		outlen     = C.size_t(len(out))
   147  	)
   148  	if C.secp256k1_ext_reencode_pubkey(context, outdata, outlen, pubkeydata, pubkeylen) == 0 {
   149  		return nil, nil
   150  	}
   151  	return new(big.Int).SetBytes(out[1:33]), new(big.Int).SetBytes(out[33:])
   152  }
   153  
   154  // CompressPubkey encodes a public key to 33-byte compressed format.
   155  func CompressPubkey(x, y *big.Int) []byte {
   156  	var (
   157  		pubkey     = S256().Marshal(x, y)
   158  		pubkeydata = (*C.uchar)(unsafe.Pointer(&pubkey[0]))
   159  		pubkeylen  = C.size_t(len(pubkey))
   160  		out        = make([]byte, 33)
   161  		outdata    = (*C.uchar)(unsafe.Pointer(&out[0]))
   162  		outlen     = C.size_t(len(out))
   163  	)
   164  	if C.secp256k1_ext_reencode_pubkey(context, outdata, outlen, pubkeydata, pubkeylen) == 0 {
   165  		panic("libsecp256k1 error")
   166  	}
   167  	return out
   168  }
   169  
   170  func checkSignature(sig []byte) error {
   171  	if len(sig) != 65 {
   172  		return ErrInvalidSignatureLen
   173  	}
   174  	if sig[64] >= 4 {
   175  		return ErrInvalidRecoveryID
   176  	}
   177  	return nil
   178  }
   179  
   180  // SchnorrVerifyMulti verifies a Schnorr signature.
   181  // Returns true iff (R, s) is a valid signature verifiable by P; false otherwise.
   182  // R and P should be uncompressed points on SECP256k1 curve with proper padding in front (i.e., starting with 0x04).
   183  // P can be a single key or a combined public key s.t. P = P0 + P1 + ... + PN where Pi is a public key for i = 0..N.
   184  // s is a 32-byte scalar.
   185  func SchnorrVerifyNative(message, R, s, P []byte) bool {
   186  	e := hash(message, P, R)
   187  	var (
   188  		Pdata = (*C.uchar)(unsafe.Pointer(&P[1])) // skipping the first byte (i.e., key format indicator such as 0x04)
   189  		Rdata = (*C.uchar)(unsafe.Pointer(&R[1])) // same here
   190  		sdata = (*C.uchar)(unsafe.Pointer(&s[0]))
   191  		edata = (*C.uchar)(unsafe.Pointer(&e[0]))
   192  	)
   193  	return 0 != C.secp256k1_ext_schnorr_verify(context, Pdata, Rdata, sdata, edata)
   194  }
   195  
   196  // ScPointMul is a simple C-binding performing multiplication between a curve point and a scalar.
   197  // Returns a point in the uncompressed format.
   198  func ScPointMul(point, a []byte) []byte {
   199  	out := make([]byte, 64)
   200  	var (
   201  		odata = (*C.uchar)(unsafe.Pointer(&out[0]))
   202  		pdata = (*C.uchar)(unsafe.Pointer(&point[1]))
   203  		adata = (*C.uchar)(unsafe.Pointer(&a[0]))
   204  	)
   205  	if C.secp256k1_ext_scalar_mul_bytes(context, odata, pdata, adata) == 0 {
   206  		panic("libsecp256k1 error")
   207  	}
   208  	return append([]byte{4}, out...) // the returned point does not have the format byte in front
   209  }
   210  
   211  // ScBaseMul is a simple C-binding performing a * G where a is an input scalar and G is SECP256k1 curve.
   212  func ScBaseMul(a []byte) []byte {
   213  	var (
   214  		out   = make([]byte, 64)
   215  		adata = (*C.uchar)(unsafe.Pointer(&a[0]))
   216  		odata = (*C.uchar)(unsafe.Pointer(&out[0]))
   217  	)
   218  	if C.secp256k1_ext_scalar_base_mult(context, odata, adata) == 0 {
   219  		panic("libsecp256k1 error")
   220  	}
   221  	return append([]byte{4}, out...)
   222  }
   223  
   224  // ScMul is a simple C-binding performing multiplication for two input scalars.
   225  func ScMul(a, b []byte) []byte {
   226  	var (
   227  		out   = make([]byte, 32)
   228  		adata = (*C.uchar)(unsafe.Pointer(&a[0]))
   229  		bdata = (*C.uchar)(unsafe.Pointer(&b[0]))
   230  		odata = (*C.uchar)(unsafe.Pointer(&out[0]))
   231  	)
   232  	C.secp256k1_ext_sc_mul(odata, adata, bdata)
   233  	return out
   234  }
   235  
   236  // ScSub is a simple C-binding performing subtraction between two input scalars.
   237  func ScSub(a, b []byte) []byte {
   238  	var (
   239  		out   = make([]byte, 32)
   240  		adata = (*C.uchar)(unsafe.Pointer(&a[0]))
   241  		bdata = (*C.uchar)(unsafe.Pointer(&b[0]))
   242  		odata = (*C.uchar)(unsafe.Pointer(&out[0]))
   243  	)
   244  	C.secp256k1_ext_sc_sub(odata, adata, bdata)
   245  	return out
   246  }
   247  
   248  // ScAdd is a simple C-binding performing addition between two input scalars.
   249  func ScAdd(a, b []byte) []byte {
   250  	var (
   251  		out   = make([]byte, 32)
   252  		adata = (*C.uchar)(unsafe.Pointer(&a[0]))
   253  		bdata = (*C.uchar)(unsafe.Pointer(&b[0]))
   254  		odata = (*C.uchar)(unsafe.Pointer(&out[0]))
   255  	)
   256  	C.secp256k1_ext_sc_add(odata, adata, bdata)
   257  	return out
   258  }