secp256.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. package secp256k1
  17. // TODO: set USE_SCALAR_4X64 depending on platform?
  18. /*
  19. #cgo CFLAGS: -I./libsecp256k1
  20. #cgo CFLAGS: -I./libsecp256k1/src/
  21. #define USE_NUM_NONE
  22. #define USE_FIELD_10X26
  23. #define USE_FIELD_INV_BUILTIN
  24. #define USE_SCALAR_8X32
  25. #define USE_SCALAR_INV_BUILTIN
  26. #define NDEBUG
  27. #include "./libsecp256k1/src/secp256k1.c"
  28. #include "./libsecp256k1/src/modules/recovery/main_impl.h"
  29. #include "pubkey_scalar_mul.h"
  30. typedef void (*callbackFunc) (const char* msg, void* data);
  31. extern void secp256k1GoPanicIllegal(const char* msg, void* data);
  32. extern void secp256k1GoPanicError(const char* msg, void* data);
  33. */
  34. import "C"
  35. import (
  36. "errors"
  37. "math/big"
  38. "unsafe"
  39. "github.com/ethereum/go-ethereum/crypto/randentropy"
  40. )
  41. //#define USE_FIELD_5X64
  42. /*
  43. TODO:
  44. > store private keys in buffer and shuffle (deters persistence on swap disc)
  45. > byte permutation (changing)
  46. > xor with chaning random block (to deter scanning memory for 0x63) (stream cipher?)
  47. */
  48. // holds ptr to secp256k1_context_struct (see secp256k1/include/secp256k1.h)
  49. var (
  50. context *C.secp256k1_context
  51. N *big.Int
  52. HalfN *big.Int
  53. )
  54. func init() {
  55. N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
  56. // N / 2 == 57896044618658097711785492504343953926418782139537452191302581570759080747168
  57. HalfN, _ = new(big.Int).SetString("7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0", 16)
  58. // around 20 ms on a modern CPU.
  59. context = C.secp256k1_context_create(3) // SECP256K1_START_SIGN | SECP256K1_START_VERIFY
  60. C.secp256k1_context_set_illegal_callback(context, C.callbackFunc(C.secp256k1GoPanicIllegal), nil)
  61. C.secp256k1_context_set_error_callback(context, C.callbackFunc(C.secp256k1GoPanicError), nil)
  62. }
  63. var (
  64. ErrInvalidMsgLen = errors.New("invalid message length for signature recovery")
  65. ErrInvalidSignatureLen = errors.New("invalid signature length")
  66. ErrInvalidRecoveryID = errors.New("invalid signature recovery id")
  67. )
  68. func GenerateKeyPair() ([]byte, []byte) {
  69. var seckey []byte = randentropy.GetEntropyCSPRNG(32)
  70. var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
  71. var pubkey64 []byte = make([]byte, 64) // secp256k1_pubkey
  72. var pubkey65 []byte = make([]byte, 65) // 65 byte uncompressed pubkey
  73. pubkey64_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey64[0]))
  74. pubkey65_ptr := (*C.uchar)(unsafe.Pointer(&pubkey65[0]))
  75. ret := C.secp256k1_ec_pubkey_create(
  76. context,
  77. pubkey64_ptr,
  78. seckey_ptr,
  79. )
  80. if ret != C.int(1) {
  81. return GenerateKeyPair() // invalid secret, try again
  82. }
  83. var output_len C.size_t
  84. C.secp256k1_ec_pubkey_serialize( // always returns 1
  85. context,
  86. pubkey65_ptr,
  87. &output_len,
  88. pubkey64_ptr,
  89. 0, // SECP256K1_EC_COMPRESSED
  90. )
  91. return pubkey65, seckey
  92. }
  93. func GeneratePubKey(seckey []byte) ([]byte, error) {
  94. if err := VerifySeckeyValidity(seckey); err != nil {
  95. return nil, err
  96. }
  97. var pubkey []byte = make([]byte, 64)
  98. var pubkey_ptr *C.secp256k1_pubkey = (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0]))
  99. var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
  100. ret := C.secp256k1_ec_pubkey_create(
  101. context,
  102. pubkey_ptr,
  103. seckey_ptr,
  104. )
  105. if ret != C.int(1) {
  106. return nil, errors.New("Unable to generate pubkey from seckey")
  107. }
  108. return pubkey, nil
  109. }
  110. func Sign(msg []byte, seckey []byte) ([]byte, error) {
  111. msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0]))
  112. seckey_ptr := (*C.uchar)(unsafe.Pointer(&seckey[0]))
  113. sig := make([]byte, 65)
  114. sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&sig[0]))
  115. nonce := randentropy.GetEntropyCSPRNG(32)
  116. ndata_ptr := unsafe.Pointer(&nonce[0])
  117. noncefp_ptr := &(*C.secp256k1_nonce_function_default)
  118. if C.secp256k1_ec_seckey_verify(context, seckey_ptr) != C.int(1) {
  119. return nil, errors.New("Invalid secret key")
  120. }
  121. ret := C.secp256k1_ecdsa_sign_recoverable(
  122. context,
  123. sig_ptr,
  124. msg_ptr,
  125. seckey_ptr,
  126. noncefp_ptr,
  127. ndata_ptr,
  128. )
  129. if ret == C.int(0) {
  130. return Sign(msg, seckey) //invalid secret, try again
  131. }
  132. sig_serialized := make([]byte, 65)
  133. sig_serialized_ptr := (*C.uchar)(unsafe.Pointer(&sig_serialized[0]))
  134. var recid C.int
  135. C.secp256k1_ecdsa_recoverable_signature_serialize_compact(
  136. context,
  137. sig_serialized_ptr, // 64 byte compact signature
  138. &recid,
  139. sig_ptr, // 65 byte "recoverable" signature
  140. )
  141. sig_serialized[64] = byte(int(recid)) // add back recid to get 65 bytes sig
  142. return sig_serialized, nil
  143. }
  144. func VerifySeckeyValidity(seckey []byte) error {
  145. if len(seckey) != 32 {
  146. return errors.New("priv key is not 32 bytes")
  147. }
  148. var seckey_ptr *C.uchar = (*C.uchar)(unsafe.Pointer(&seckey[0]))
  149. ret := C.secp256k1_ec_seckey_verify(context, seckey_ptr)
  150. if int(ret) != 1 {
  151. return errors.New("invalid seckey")
  152. }
  153. return nil
  154. }
  155. // RecoverPubkey returns the the public key of the signer.
  156. // msg must be the 32-byte hash of the message to be signed.
  157. // sig must be a 65-byte compact ECDSA signature containing the
  158. // recovery id as the last element.
  159. func RecoverPubkey(msg []byte, sig []byte) ([]byte, error) {
  160. if len(msg) != 32 {
  161. return nil, ErrInvalidMsgLen
  162. }
  163. if err := checkSignature(sig); err != nil {
  164. return nil, err
  165. }
  166. msg_ptr := (*C.uchar)(unsafe.Pointer(&msg[0]))
  167. sig_ptr := (*C.uchar)(unsafe.Pointer(&sig[0]))
  168. pubkey := make([]byte, 64)
  169. /*
  170. this slice is used for both the recoverable signature and the
  171. resulting serialized pubkey (both types in libsecp256k1 are 65
  172. bytes). this saves one allocation of 65 bytes, which is nice as
  173. pubkey recovery is one bottleneck during load in Ethereum
  174. */
  175. bytes65 := make([]byte, 65)
  176. pubkey_ptr := (*C.secp256k1_pubkey)(unsafe.Pointer(&pubkey[0]))
  177. recoverable_sig_ptr := (*C.secp256k1_ecdsa_recoverable_signature)(unsafe.Pointer(&bytes65[0]))
  178. recid := C.int(sig[64])
  179. ret := C.secp256k1_ecdsa_recoverable_signature_parse_compact(
  180. context,
  181. recoverable_sig_ptr,
  182. sig_ptr,
  183. recid)
  184. if ret == C.int(0) {
  185. return nil, errors.New("Failed to parse signature")
  186. }
  187. ret = C.secp256k1_ecdsa_recover(
  188. context,
  189. pubkey_ptr,
  190. recoverable_sig_ptr,
  191. msg_ptr,
  192. )
  193. if ret == C.int(0) {
  194. return nil, errors.New("Failed to recover public key")
  195. }
  196. serialized_pubkey_ptr := (*C.uchar)(unsafe.Pointer(&bytes65[0]))
  197. var output_len C.size_t
  198. C.secp256k1_ec_pubkey_serialize( // always returns 1
  199. context,
  200. serialized_pubkey_ptr,
  201. &output_len,
  202. pubkey_ptr,
  203. 0, // SECP256K1_EC_COMPRESSED
  204. )
  205. return bytes65, nil
  206. }
  207. func checkSignature(sig []byte) error {
  208. if len(sig) != 65 {
  209. return ErrInvalidSignatureLen
  210. }
  211. if sig[64] >= 4 {
  212. return ErrInvalidRecoveryID
  213. }
  214. return nil
  215. }
  216. // reads num into buf as big-endian bytes.
  217. func readBits(buf []byte, num *big.Int) {
  218. const wordLen = int(unsafe.Sizeof(big.Word(0)))
  219. i := len(buf)
  220. for _, d := range num.Bits() {
  221. for j := 0; j < wordLen && i > 0; j++ {
  222. i--
  223. buf[i] = byte(d)
  224. d >>= 8
  225. }
  226. }
  227. }