ecc_fast.py (5934B)
1 # taken (with minor modifications) from pycoin 2 # https://github.com/richardkiss/pycoin/blob/01b1787ed902df23f99a55deb00d8cd076a906fe/pycoin/ecdsa/native/secp256k1.py 3 4 import os 5 import sys 6 import traceback 7 import ctypes 8 from ctypes import ( 9 byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer, 10 CFUNCTYPE, POINTER, cast 11 ) 12 13 from .logging import get_logger 14 15 16 _logger = get_logger(__name__) 17 18 19 SECP256K1_FLAGS_TYPE_MASK = ((1 << 8) - 1) 20 SECP256K1_FLAGS_TYPE_CONTEXT = (1 << 0) 21 SECP256K1_FLAGS_TYPE_COMPRESSION = (1 << 1) 22 # /** The higher bits contain the actual data. Do not use directly. */ 23 SECP256K1_FLAGS_BIT_CONTEXT_VERIFY = (1 << 8) 24 SECP256K1_FLAGS_BIT_CONTEXT_SIGN = (1 << 9) 25 SECP256K1_FLAGS_BIT_COMPRESSION = (1 << 8) 26 27 # /** Flags to pass to secp256k1_context_create. */ 28 SECP256K1_CONTEXT_VERIFY = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_VERIFY) 29 SECP256K1_CONTEXT_SIGN = (SECP256K1_FLAGS_TYPE_CONTEXT | SECP256K1_FLAGS_BIT_CONTEXT_SIGN) 30 SECP256K1_CONTEXT_NONE = (SECP256K1_FLAGS_TYPE_CONTEXT) 31 32 SECP256K1_EC_COMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION | SECP256K1_FLAGS_BIT_COMPRESSION) 33 SECP256K1_EC_UNCOMPRESSED = (SECP256K1_FLAGS_TYPE_COMPRESSION) 34 35 36 class LibModuleMissing(Exception): pass 37 38 39 def load_library(): 40 if sys.platform == 'darwin': 41 library_paths = (os.path.join(os.path.dirname(__file__), 'libsecp256k1.0.dylib'), 42 'libsecp256k1.0.dylib') 43 elif sys.platform in ('windows', 'win32'): 44 library_paths = (os.path.join(os.path.dirname(__file__), 'libsecp256k1-0.dll'), 45 'libsecp256k1-0.dll') 46 elif 'ANDROID_DATA' in os.environ: 47 library_paths = ('libsecp256k1.so',) 48 else: # desktop Linux and similar 49 library_paths = (os.path.join(os.path.dirname(__file__), 'libsecp256k1.so.0'), 50 'libsecp256k1.so.0') 51 52 exceptions = [] 53 secp256k1 = None 54 for libpath in library_paths: 55 try: 56 secp256k1 = ctypes.cdll.LoadLibrary(libpath) 57 except BaseException as e: 58 exceptions.append(e) 59 else: 60 break 61 if not secp256k1: 62 _logger.error(f'libsecp256k1 library failed to load. exceptions: {repr(exceptions)}') 63 return None 64 65 try: 66 secp256k1.secp256k1_context_create.argtypes = [c_uint] 67 secp256k1.secp256k1_context_create.restype = c_void_p 68 69 secp256k1.secp256k1_context_randomize.argtypes = [c_void_p, c_char_p] 70 secp256k1.secp256k1_context_randomize.restype = c_int 71 72 secp256k1.secp256k1_ec_pubkey_create.argtypes = [c_void_p, c_void_p, c_char_p] 73 secp256k1.secp256k1_ec_pubkey_create.restype = c_int 74 75 secp256k1.secp256k1_ecdsa_sign.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p, c_void_p, c_void_p] 76 secp256k1.secp256k1_ecdsa_sign.restype = c_int 77 78 secp256k1.secp256k1_ecdsa_verify.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p] 79 secp256k1.secp256k1_ecdsa_verify.restype = c_int 80 81 secp256k1.secp256k1_ec_pubkey_parse.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t] 82 secp256k1.secp256k1_ec_pubkey_parse.restype = c_int 83 84 secp256k1.secp256k1_ec_pubkey_serialize.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p, c_uint] 85 secp256k1.secp256k1_ec_pubkey_serialize.restype = c_int 86 87 secp256k1.secp256k1_ecdsa_signature_parse_compact.argtypes = [c_void_p, c_char_p, c_char_p] 88 secp256k1.secp256k1_ecdsa_signature_parse_compact.restype = c_int 89 90 secp256k1.secp256k1_ecdsa_signature_normalize.argtypes = [c_void_p, c_char_p, c_char_p] 91 secp256k1.secp256k1_ecdsa_signature_normalize.restype = c_int 92 93 secp256k1.secp256k1_ecdsa_signature_serialize_compact.argtypes = [c_void_p, c_char_p, c_char_p] 94 secp256k1.secp256k1_ecdsa_signature_serialize_compact.restype = c_int 95 96 secp256k1.secp256k1_ecdsa_signature_parse_der.argtypes = [c_void_p, c_char_p, c_char_p, c_size_t] 97 secp256k1.secp256k1_ecdsa_signature_parse_der.restype = c_int 98 99 secp256k1.secp256k1_ecdsa_signature_serialize_der.argtypes = [c_void_p, c_char_p, c_void_p, c_char_p] 100 secp256k1.secp256k1_ecdsa_signature_serialize_der.restype = c_int 101 102 secp256k1.secp256k1_ec_pubkey_tweak_mul.argtypes = [c_void_p, c_char_p, c_char_p] 103 secp256k1.secp256k1_ec_pubkey_tweak_mul.restype = c_int 104 105 secp256k1.secp256k1_ec_pubkey_combine.argtypes = [c_void_p, c_char_p, c_void_p, c_size_t] 106 secp256k1.secp256k1_ec_pubkey_combine.restype = c_int 107 108 # --enable-module-recovery 109 try: 110 secp256k1.secp256k1_ecdsa_recover.argtypes = [c_void_p, c_char_p, c_char_p, c_char_p] 111 secp256k1.secp256k1_ecdsa_recover.restype = c_int 112 113 secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact.argtypes = [c_void_p, c_char_p, c_char_p, c_int] 114 secp256k1.secp256k1_ecdsa_recoverable_signature_parse_compact.restype = c_int 115 except (OSError, AttributeError): 116 raise LibModuleMissing('libsecp256k1 library found but it was built ' 117 'without required module (--enable-module-recovery)') 118 119 secp256k1.ctx = secp256k1.secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY) 120 ret = secp256k1.secp256k1_context_randomize(secp256k1.ctx, os.urandom(32)) 121 if not ret: 122 _logger.error('secp256k1_context_randomize failed') 123 return None 124 125 return secp256k1 126 except (OSError, AttributeError) as e: 127 _logger.error(f'libsecp256k1 library was found and loaded but there was an error when using it: {repr(e)}') 128 return None 129 130 131 _libsecp256k1 = None 132 try: 133 _libsecp256k1 = load_library() 134 except BaseException as e: 135 _logger.error(f'failed to load libsecp256k1: {repr(e)}') 136 137 138 if _libsecp256k1 is None: 139 # hard fail: 140 sys.exit(f"Error: Failed to load libsecp256k1.")