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 }