rev260, Fix SIGSEGV on CentOS and other platforms that dont has secp256k1 support in OpenSSL, SSLBenchmark new psutil support and use cert from data dir

This commit is contained in:
HelloZeroNet 2015-07-01 22:04:38 +02:00
parent dc791a31ab
commit 0ca0c754e6
3 changed files with 339 additions and 292 deletions

View File

@ -4,7 +4,7 @@ import ConfigParser
class Config(object): class Config(object):
def __init__(self): def __init__(self):
self.version = "0.3.1" self.version = "0.3.1"
self.rev = 259 self.rev = 260
self.parser = self.createArguments() self.parser = self.createArguments()
argv = sys.argv[:] # Copy command line arguments argv = sys.argv[:] # Copy command line arguments
argv = self.parseConfig(argv) # Add arguments from config file argv = self.parseConfig(argv) # Add arguments from config file

View File

@ -31,7 +31,7 @@ def handle(sock_raw, addr):
break break
elif line == "gotssl\n": elif line == "gotssl\n":
sock.sendall("yes\n") sock.sendall("yes\n")
sock = gevent.ssl.wrap_socket(sock_raw, server_side=True, keyfile='src/Test/testdata/key-rsa.pem', certfile='src/Test/testdata/cert-rsa.pem', ciphers=ciphers) sock = gevent.ssl.wrap_socket(sock_raw, server_side=True, keyfile='data/key-rsa.pem', certfile='data/cert-rsa.pem', ciphers=ciphers)
else: else:
sock.sendall(data) sock.sendall(data)
except Exception, err: except Exception, err:
@ -69,7 +69,7 @@ def getData():
#clipher = sock.cipher() #clipher = sock.cipher()
sock.send("gotssl\n") sock.send("gotssl\n")
if sock.recv(128) == "yes\n": if sock.recv(128) == "yes\n":
sock = ssl.wrap_socket(sock, ciphers=ciphers) sock = ssl.wrap_socket(sock, ciphers=ciphers, ssl_version=ssl.PROTOCOL_TLSv1)
sock.do_handshake() sock.do_handshake()
clipher = sock.cipher() clipher = sock.cipher()
@ -98,8 +98,12 @@ s = time.time()
def info(): def info():
import psutil, os import psutil, os
process = psutil.Process(os.getpid()) process = psutil.Process(os.getpid())
if "memory_info" in dir(process):
memory_info = process.memory_info
else:
memory_info = process.get_memory_info
while 1: while 1:
print total_num, "req", (total_bytes/1024), "kbytes", "transfered in", time.time()-s, "using", clipher, "Mem:", process.get_memory_info()[0] / float(2 ** 20) print total_num, "req", (total_bytes/1024), "kbytes", "transfered in", time.time()-s, "using", clipher, "Mem:", memory_info()[0] / float(2 ** 20)
time.sleep(1) time.sleep(1)
gevent.spawn(info) gevent.spawn(info)

View File

@ -12,195 +12,205 @@ import hashlib
import base64 import base64
import time import time
import logging import logging
import sys
addrtype = 0 addrtype = 0
class _OpenSSL: class _OpenSSL:
"""
Wrapper for OpenSSL using ctypes
"""
def __init__(self, library):
self.time_opened = time.time()
"""
Build the wrapper
"""
try:
self._lib = ctypes.CDLL(library)
except:
self._lib = ctypes.cdll.LoadLibrary(library)
self.pointer = ctypes.pointer """
self.c_int = ctypes.c_int Wrapper for OpenSSL using ctypes
self.byref = ctypes.byref """
self.create_string_buffer = ctypes.create_string_buffer
self.BN_new = self._lib.BN_new def __init__(self, library):
self.BN_new.restype = ctypes.c_void_p self.time_opened = time.time()
self.BN_new.argtypes = [] """
Build the wrapper
"""
try:
self._lib = ctypes.CDLL(library)
except:
self._lib = ctypes.cdll.LoadLibrary(library)
self.BN_copy = self._lib.BN_copy self.pointer = ctypes.pointer
self.BN_copy.restype = ctypes.c_void_p self.c_int = ctypes.c_int
self.BN_copy.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.byref = ctypes.byref
self.create_string_buffer = ctypes.create_string_buffer
self.BN_mul_word = self._lib.BN_mul_word self.BN_new = self._lib.BN_new
self.BN_mul_word.restype = ctypes.c_int self.BN_new.restype = ctypes.c_void_p
self.BN_mul_word.argtypes = [ctypes.c_void_p, ctypes.c_int] self.BN_new.argtypes = []
self.BN_set_word = self._lib.BN_set_word self.BN_copy = self._lib.BN_copy
self.BN_set_word.restype = ctypes.c_int self.BN_copy.restype = ctypes.c_void_p
self.BN_set_word.argtypes = [ctypes.c_void_p, ctypes.c_int] self.BN_copy.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.BN_add = self._lib.BN_add self.BN_mul_word = self._lib.BN_mul_word
self.BN_add.restype = ctypes.c_void_p self.BN_mul_word.restype = ctypes.c_int
self.BN_add.argtypes = [ctypes.c_void_p, ctypes.c_void_p, self.BN_mul_word.argtypes = [ctypes.c_void_p, ctypes.c_int]
ctypes.c_void_p]
self.BN_mod_sub = self._lib.BN_mod_sub self.BN_set_word = self._lib.BN_set_word
self.BN_mod_sub.restype = ctypes.c_int self.BN_set_word.restype = ctypes.c_int
self.BN_mod_sub.argtypes = [ctypes.c_void_p, ctypes.c_void_p, self.BN_set_word.argtypes = [ctypes.c_void_p, ctypes.c_int]
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p]
self.BN_mod_mul = self._lib.BN_mod_mul self.BN_add = self._lib.BN_add
self.BN_mod_mul.restype = ctypes.c_int self.BN_add.restype = ctypes.c_void_p
self.BN_mod_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, self.BN_add.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p]
ctypes.c_void_p,
ctypes.c_void_p]
self.BN_mod_inverse = self._lib.BN_mod_inverse self.BN_mod_sub = self._lib.BN_mod_sub
self.BN_mod_inverse.restype = ctypes.c_void_p self.BN_mod_sub.restype = ctypes.c_int
self.BN_mod_inverse.argtypes = [ctypes.c_void_p, ctypes.c_void_p, self.BN_mod_sub.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p] ctypes.c_void_p,
ctypes.c_void_p]
self.BN_cmp = self._lib.BN_cmp self.BN_mod_mul = self._lib.BN_mod_mul
self.BN_cmp.restype = ctypes.c_int self.BN_mod_mul.restype = ctypes.c_int
self.BN_cmp.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.BN_mod_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p]
self.BN_bn2bin = self._lib.BN_bn2bin self.BN_mod_inverse = self._lib.BN_mod_inverse
self.BN_bn2bin.restype = ctypes.c_int self.BN_mod_inverse.restype = ctypes.c_void_p
self.BN_bn2bin.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.BN_mod_inverse.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p]
self.BN_bin2bn = self._lib.BN_bin2bn self.BN_cmp = self._lib.BN_cmp
self.BN_bin2bn.restype = ctypes.c_void_p self.BN_cmp.restype = ctypes.c_int
self.BN_bin2bn.argtypes = [ctypes.c_void_p, ctypes.c_int, self.BN_cmp.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
ctypes.c_void_p]
self.EC_KEY_new_by_curve_name = self._lib.EC_KEY_new_by_curve_name self.BN_bn2bin = self._lib.BN_bn2bin
self.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p self.BN_bn2bin.restype = ctypes.c_int
self.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int] self.BN_bn2bin.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.EC_KEY_get0_group = self._lib.EC_KEY_get0_group self.BN_bin2bn = self._lib.BN_bin2bn
self.EC_KEY_get0_group.restype = ctypes.c_void_p self.BN_bin2bn.restype = ctypes.c_void_p
self.EC_KEY_get0_group.argtypes = [ctypes.c_void_p] self.BN_bin2bn.argtypes = [ctypes.c_void_p, ctypes.c_int,
ctypes.c_void_p]
self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key self.EC_KEY_new_by_curve_name = self._lib.EC_KEY_new_by_curve_name
self.EC_KEY_set_private_key.restype = ctypes.c_int self.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, self.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int]
ctypes.c_void_p]
self.EC_KEY_set_public_key = self._lib.EC_KEY_set_public_key self.EC_KEY_get0_group = self._lib.EC_KEY_get0_group
self.EC_KEY_set_public_key.restype = ctypes.c_int self.EC_KEY_get0_group.restype = ctypes.c_void_p
self.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p, self.EC_KEY_get0_group.argtypes = [ctypes.c_void_p]
ctypes.c_void_p]
self.EC_POINT_set_compressed_coordinates_GFp = self._lib.EC_POINT_set_compressed_coordinates_GFp self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
self.EC_POINT_set_compressed_coordinates_GFp.restype = ctypes.c_int self.EC_KEY_set_private_key.restype = ctypes.c_int
self.EC_POINT_set_compressed_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p] self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p,
ctypes.c_void_p]
self.EC_POINT_new = self._lib.EC_POINT_new self.EC_KEY_set_public_key = self._lib.EC_KEY_set_public_key
self.EC_POINT_new.restype = ctypes.c_void_p self.EC_KEY_set_public_key.restype = ctypes.c_int
self.EC_POINT_new.argtypes = [ctypes.c_void_p] self.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p,
ctypes.c_void_p]
self.EC_POINT_free = self._lib.EC_POINT_free self.EC_POINT_set_compressed_coordinates_GFp = self._lib.EC_POINT_set_compressed_coordinates_GFp
self.EC_POINT_free.restype = None self.EC_POINT_set_compressed_coordinates_GFp.restype = ctypes.c_int
self.EC_POINT_free.argtypes = [ctypes.c_void_p] self.EC_POINT_set_compressed_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
self.EC_GROUP_get_order = self._lib.EC_GROUP_get_order self.EC_POINT_new = self._lib.EC_POINT_new
self.EC_GROUP_get_order.restype = ctypes.c_void_p self.EC_POINT_new.restype = ctypes.c_void_p
self.EC_GROUP_get_order.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p] self.EC_POINT_new.argtypes = [ctypes.c_void_p]
self.EC_GROUP_get_degree = self._lib.EC_GROUP_get_degree self.EC_POINT_free = self._lib.EC_POINT_free
self.EC_GROUP_get_degree.restype = ctypes.c_void_p self.EC_POINT_free.restype = None
self.EC_GROUP_get_degree.argtypes = [ctypes.c_void_p] self.EC_POINT_free.argtypes = [ctypes.c_void_p]
self.EC_GROUP_get_curve_GFp = self._lib.EC_GROUP_get_curve_GFp self.EC_GROUP_get_order = self._lib.EC_GROUP_get_order
self.EC_GROUP_get_curve_GFp.restype = ctypes.c_void_p self.EC_GROUP_get_order.restype = ctypes.c_void_p
self.EC_GROUP_get_curve_GFp.argtypes = [ctypes.c_void_p, self.EC_GROUP_get_order.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p]
self.EC_POINT_mul = self._lib.EC_POINT_mul self.EC_GROUP_get_degree = self._lib.EC_GROUP_get_degree
self.EC_POINT_mul.restype = ctypes.c_int self.EC_GROUP_get_degree.restype = ctypes.c_void_p
self.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, self.EC_GROUP_get_degree.argtypes = [ctypes.c_void_p]
ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p]
self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key self.EC_GROUP_get_curve_GFp = self._lib.EC_GROUP_get_curve_GFp
self.EC_KEY_set_private_key.restype = ctypes.c_int self.EC_GROUP_get_curve_GFp.restype = ctypes.c_void_p
self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, self.EC_GROUP_get_curve_GFp.argtypes = [ctypes.c_void_p,
ctypes.c_void_p] ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p]
self.EC_KEY_set_conv_form = self._lib.EC_KEY_set_conv_form self.EC_POINT_mul = self._lib.EC_POINT_mul
self.EC_KEY_set_conv_form.restype = None self.EC_POINT_mul.restype = ctypes.c_int
self.EC_KEY_set_conv_form.argtypes = [ctypes.c_void_p, self.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_int] ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_void_p, ctypes.c_void_p]
self.BN_CTX_new = self._lib.BN_CTX_new self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
self._lib.BN_CTX_new.restype = ctypes.c_void_p self.EC_KEY_set_private_key.restype = ctypes.c_int
self._lib.BN_CTX_new.argtypes = [] self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p,
ctypes.c_void_p]
self.BN_CTX_start = self._lib.BN_CTX_start self.EC_KEY_set_conv_form = self._lib.EC_KEY_set_conv_form
self._lib.BN_CTX_start.restype = ctypes.c_void_p self.EC_KEY_set_conv_form.restype = None
self._lib.BN_CTX_start.argtypes = [ctypes.c_void_p] self.EC_KEY_set_conv_form.argtypes = [ctypes.c_void_p,
ctypes.c_int]
self.BN_CTX_get = self._lib.BN_CTX_get self.BN_CTX_new = self._lib.BN_CTX_new
self._lib.BN_CTX_get.restype = ctypes.c_void_p self._lib.BN_CTX_new.restype = ctypes.c_void_p
self._lib.BN_CTX_get.argtypes = [ctypes.c_void_p] self._lib.BN_CTX_new.argtypes = []
self.ECDSA_sign = self._lib.ECDSA_sign self.BN_CTX_start = self._lib.BN_CTX_start
self.ECDSA_sign.restype = ctypes.c_int self._lib.BN_CTX_start.restype = ctypes.c_void_p
self.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, self._lib.BN_CTX_start.argtypes = [ctypes.c_void_p]
ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
self.ECDSA_verify = self._lib.ECDSA_verify self.BN_CTX_get = self._lib.BN_CTX_get
self.ECDSA_verify.restype = ctypes.c_int self._lib.BN_CTX_get.restype = ctypes.c_void_p
self.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p, self._lib.BN_CTX_get.argtypes = [ctypes.c_void_p]
ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
self.i2o_ECPublicKey = self._lib.i2o_ECPublicKey self.ECDSA_sign = self._lib.ECDSA_sign
self.i2o_ECPublicKey.restype = ctypes.c_void_p self.ECDSA_sign.restype = ctypes.c_int
self.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p] self.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
self.BN_CTX_free = self._lib.BN_CTX_free self.ECDSA_verify = self._lib.ECDSA_verify
self.BN_CTX_free.restype = None self.ECDSA_verify.restype = ctypes.c_int
self.BN_CTX_free.argtypes = [ctypes.c_void_p] self.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p,
ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
self.EC_POINT_free = self._lib.EC_POINT_free self.i2o_ECPublicKey = self._lib.i2o_ECPublicKey
self.EC_POINT_free.restype = None self.i2o_ECPublicKey.restype = ctypes.c_void_p
self.EC_POINT_free.argtypes = [ctypes.c_void_p] self.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
self.BN_CTX_free = self._lib.BN_CTX_free
self.BN_CTX_free.restype = None
self.BN_CTX_free.argtypes = [ctypes.c_void_p]
self.EC_POINT_free = self._lib.EC_POINT_free
self.EC_POINT_free.restype = None
self.EC_POINT_free.argtypes = [ctypes.c_void_p]
ssl = None
def openLibrary(): def openLibrary():
global ssl global ssl
try: try:
ssl = _OpenSSL("src/lib/opensslVerify/libeay32.dll") if sys.platform.startswith("win"):
except: ssl = _OpenSSL("src/lib/opensslVerify/libeay32.dll")
ssl = _OpenSSL(ctypes.util.find_library('ssl') or ctypes.util.find_library('crypto') or 'libeay32') else: # Try to use self-compiled first
ssl = _OpenSSL("/usr/local/ssl/lib/libcrypto.so")
except:
ssl = _OpenSSL(ctypes.util.find_library('ssl') or ctypes.util.find_library('crypto') or 'libeay32')
openLibrary() openLibrary()
openssl_version = "%.9X" % ssl._lib.SSLeay() openssl_version = "%.9X" % ssl._lib.SSLeay()
NID_secp256k1 = 714 NID_secp256k1 = 714
def check_result (val, func, args):
if val == 0: def check_result(val, func, args):
raise ValueError if val == 0:
else: raise ValueError
return ctypes.c_void_p (val) else:
return ctypes.c_void_p(val)
ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p ssl.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
ssl.EC_KEY_new_by_curve_name.errcheck = check_result ssl.EC_KEY_new_by_curve_name.errcheck = check_result
@ -211,193 +221,226 @@ POINT_CONVERSION_UNCOMPRESSED = 4
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars) __b58base = len(__b58chars)
def b58encode(v): def b58encode(v):
""" encode v, which is a string of bytes, to base58. """ encode v, which is a string of bytes, to base58.
""" """
long_value = 0L long_value = 0L
for (i, c) in enumerate(v[::-1]): for (i, c) in enumerate(v[::-1]):
long_value += (256**i) * ord(c) long_value += (256 ** i) * ord(c)
result = '' result = ''
while long_value >= __b58base: while long_value >= __b58base:
div, mod = divmod(long_value, __b58base) div, mod = divmod(long_value, __b58base)
result = __b58chars[mod] + result result = __b58chars[mod] + result
long_value = div long_value = div
result = __b58chars[long_value] + result result = __b58chars[long_value] + result
# Bitcoin does a little leading-zero-compression: # Bitcoin does a little leading-zero-compression:
# leading 0-bytes in the input become leading-1s # leading 0-bytes in the input become leading-1s
nPad = 0 nPad = 0
for c in v: for c in v:
if c == '\0': nPad += 1 if c == '\0':
else: break nPad += 1
else:
break
return (__b58chars[0] * nPad) + result
return (__b58chars[0]*nPad) + result
def hash_160(public_key): def hash_160(public_key):
md = hashlib.new('ripemd160') md = hashlib.new('ripemd160')
md.update(hashlib.sha256(public_key).digest()) md.update(hashlib.sha256(public_key).digest())
return md.digest() return md.digest()
def hash_160_to_bc_address(h160): def hash_160_to_bc_address(h160):
vh160 = chr(addrtype) + h160 vh160 = chr(addrtype) + h160
h = Hash(vh160) h = Hash(vh160)
addr = vh160 + h[0:4] addr = vh160 + h[0:4]
return b58encode(addr) return b58encode(addr)
def public_key_to_bc_address(public_key): def public_key_to_bc_address(public_key):
h160 = hash_160(public_key) h160 = hash_160(public_key)
return hash_160_to_bc_address(h160) return hash_160_to_bc_address(h160)
def encode(val, base, minlen=0): def encode(val, base, minlen=0):
base, minlen = int(base), int(minlen) base, minlen = int(base), int(minlen)
code_string = ''.join([chr(x) for x in range(256)]) code_string = ''.join([chr(x) for x in range(256)])
result = "" result = ""
while val > 0: while val > 0:
result = code_string[val % base] + result result = code_string[val % base] + result
val //= base val //= base
return code_string[0] * max(minlen - len(result), 0) + result return code_string[0] * max(minlen - len(result), 0) + result
def num_to_var_int(x): def num_to_var_int(x):
x = int(x) x = int(x)
if x < 253: return chr(x) if x < 253:
elif x < 65536: return chr(253)+encode(x, 256, 2)[::-1] return chr(x)
elif x < 4294967296: return chr(254) + encode(x, 256, 4)[::-1] elif x < 65536:
else: return chr(255) + encode(x, 256, 8)[::-1] return chr(253) + encode(x, 256, 2)[::-1]
elif x < 4294967296:
return chr(254) + encode(x, 256, 4)[::-1]
else:
return chr(255) + encode(x, 256, 8)[::-1]
def msg_magic(message): def msg_magic(message):
return "\x18Bitcoin Signed Message:\n" + num_to_var_int( len(message) ) + message return "\x18Bitcoin Signed Message:\n" + num_to_var_int(len(message)) + message
def get_address(eckey): def get_address(eckey):
size = ssl.i2o_ECPublicKey (eckey, 0) size = ssl.i2o_ECPublicKey(eckey, 0)
mb = ctypes.create_string_buffer (size) mb = ctypes.create_string_buffer(size)
ssl.i2o_ECPublicKey (eckey, ctypes.byref (ctypes.pointer (mb))) ssl.i2o_ECPublicKey(eckey, ctypes.byref(ctypes.pointer(mb)))
return public_key_to_bc_address(mb.raw) return public_key_to_bc_address(mb.raw)
def Hash(data): def Hash(data):
return hashlib.sha256(hashlib.sha256(data).digest()).digest() return hashlib.sha256(hashlib.sha256(data).digest()).digest()
def bx(bn, size=32): def bx(bn, size=32):
b = ctypes.create_string_buffer(size) b = ctypes.create_string_buffer(size)
ssl.BN_bn2bin(bn, b); ssl.BN_bn2bin(bn, b)
return b.raw.encode('hex') return b.raw.encode('hex')
def verify_message(address, signature, message): def verify_message(address, signature, message):
pkey = ssl.EC_KEY_new_by_curve_name(NID_secp256k1) pkey = ssl.EC_KEY_new_by_curve_name(NID_secp256k1)
eckey = SetCompactSignature(pkey, Hash(msg_magic(message)), signature) eckey = SetCompactSignature(pkey, Hash(msg_magic(message)), signature)
addr = get_address(eckey) addr = get_address(eckey)
return (address == addr) return (address == addr)
def SetCompactSignature(pkey, hash, signature): def SetCompactSignature(pkey, hash, signature):
sig = base64.b64decode(signature) sig = base64.b64decode(signature)
if len(sig) != 65: if len(sig) != 65:
raise BaseException("Wrong encoding") raise BaseException("Wrong encoding")
nV = ord(sig[0]) nV = ord(sig[0])
if nV < 27 or nV >= 35: if nV < 27 or nV >= 35:
return False return False
if nV >= 31: if nV >= 31:
ssl.EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED) ssl.EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED)
nV -= 4 nV -= 4
r = ssl.BN_bin2bn (sig[1:33], 32, None) r = ssl.BN_bin2bn(sig[1:33], 32, None)
s = ssl.BN_bin2bn (sig[33:], 32, None) s = ssl.BN_bin2bn(sig[33:], 32, None)
eckey = ECDSA_SIG_recover_key_GFp(pkey, r, s, hash, len(hash), nV - 27, eckey = ECDSA_SIG_recover_key_GFp(pkey, r, s, hash, len(hash), nV - 27,
False); False)
return eckey return eckey
def ECDSA_SIG_recover_key_GFp(eckey, r, s, msg, msglen, recid, check): def ECDSA_SIG_recover_key_GFp(eckey, r, s, msg, msglen, recid, check):
n = 0 n = 0
i = recid / 2 i = recid / 2
ctx = R = O = Q = None ctx = R = O = Q = None
try: try:
group = ssl.EC_KEY_get0_group(eckey) group = ssl.EC_KEY_get0_group(eckey)
ctx = ssl.BN_CTX_new() ctx = ssl.BN_CTX_new()
ssl.BN_CTX_start(ctx) ssl.BN_CTX_start(ctx)
order = ssl.BN_CTX_get(ctx) order = ssl.BN_CTX_get(ctx)
ssl.EC_GROUP_get_order(group, order, ctx) ssl.EC_GROUP_get_order(group, order, ctx)
x = ssl.BN_CTX_get(ctx) x = ssl.BN_CTX_get(ctx)
ssl.BN_copy(x, order); ssl.BN_copy(x, order)
ssl.BN_mul_word(x, i); ssl.BN_mul_word(x, i)
ssl.BN_add(x, x, r) ssl.BN_add(x, x, r)
field = ssl.BN_CTX_get(ctx) field = ssl.BN_CTX_get(ctx)
ssl.EC_GROUP_get_curve_GFp(group, field, None, None, ctx) ssl.EC_GROUP_get_curve_GFp(group, field, None, None, ctx)
if (ssl.BN_cmp(x, field) >= 0): if (ssl.BN_cmp(x, field) >= 0):
return False return False
R = ssl.EC_POINT_new(group) R = ssl.EC_POINT_new(group)
ssl.EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx) ssl.EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)
if check: if check:
O = ssl.EC_POINT_new(group) O = ssl.EC_POINT_new(group)
ssl.EC_POINT_mul(group, O, None, R, order, ctx) ssl.EC_POINT_mul(group, O, None, R, order, ctx)
if ssl.EC_POINT_is_at_infinity(group, O): if ssl.EC_POINT_is_at_infinity(group, O):
return False return False
Q = ssl.EC_POINT_new(group) Q = ssl.EC_POINT_new(group)
n = ssl.EC_GROUP_get_degree(group) n = ssl.EC_GROUP_get_degree(group)
e = ssl.BN_CTX_get(ctx) e = ssl.BN_CTX_get(ctx)
ssl.BN_bin2bn(msg, msglen, e) ssl.BN_bin2bn(msg, msglen, e)
if 8 * msglen > n: ssl.BN_rshift(e, e, 8 - (n & 7)) if 8 * msglen > n:
ssl.BN_rshift(e, e, 8 - (n & 7))
zero = ssl.BN_CTX_get(ctx)
ssl.BN_set_word(zero, 0)
ssl.BN_mod_sub(e, zero, e, order, ctx)
rr = ssl.BN_CTX_get(ctx)
ssl.BN_mod_inverse(rr, r, order, ctx)
sor = ssl.BN_CTX_get(ctx)
ssl.BN_mod_mul(sor, s, rr, order, ctx)
eor = ssl.BN_CTX_get(ctx)
ssl.BN_mod_mul(eor, e, rr, order, ctx)
ssl.EC_POINT_mul(group, Q, eor, R, sor, ctx)
ssl.EC_KEY_set_public_key(eckey, Q)
return eckey
finally:
if ctx:
ssl.BN_CTX_free(ctx)
if R:
ssl.EC_POINT_free(R)
if O:
ssl.EC_POINT_free(O)
if Q:
ssl.EC_POINT_free(Q)
zero = ssl.BN_CTX_get(ctx)
ssl.BN_set_word(zero, 0)
ssl.BN_mod_sub(e, zero, e, order, ctx)
rr = ssl.BN_CTX_get(ctx);
ssl.BN_mod_inverse(rr, r, order, ctx)
sor = ssl.BN_CTX_get(ctx)
ssl.BN_mod_mul(sor, s, rr, order, ctx)
eor = ssl.BN_CTX_get(ctx)
ssl.BN_mod_mul(eor, e, rr, order, ctx)
ssl.EC_POINT_mul(group, Q, eor, R, sor, ctx)
ssl.EC_KEY_set_public_key(eckey, Q)
return eckey
finally:
if ctx: ssl.BN_CTX_free(ctx)
if R: ssl.EC_POINT_free(R)
if O: ssl.EC_POINT_free(O)
if Q: ssl.EC_POINT_free(Q)
def closeLibrary(): def closeLibrary():
import _ctypes import _ctypes
if "FreeLibrary" in dir(_ctypes): if "FreeLibrary" in dir(_ctypes):
_ctypes.FreeLibrary(ssl._lib._handle) _ctypes.FreeLibrary(ssl._lib._handle)
else: else:
_ctypes.dlclose(ssl._lib._handle) _ctypes.dlclose(ssl._lib._handle)
def getMessagePubkey(message, sig): def getMessagePubkey(message, sig):
pkey = ssl.EC_KEY_new_by_curve_name(NID_secp256k1) pkey = ssl.EC_KEY_new_by_curve_name(NID_secp256k1)
eckey = SetCompactSignature(pkey, Hash(msg_magic(message)), sig) if not pkey.value:
size = ssl.i2o_ECPublicKey (eckey, 0) raise Exception(
mb = ctypes.create_string_buffer (size) "OpenSSL %s (%s) EC_KEY_new_by_curve_name failed: %s, probably your OpenSSL lib does not support secp256k1 elliptic curve. Please check: https://github.com/HelloZeroNet/ZeroNet/issues/132" %
ssl.i2o_ECPublicKey (eckey, ctypes.byref (ctypes.pointer (mb))) (openssl_version, ssl._lib._name, pkey.value)
pub = mb.raw )
if time.time()-ssl.time_opened>60*5: # Reopen every 5 min eckey = SetCompactSignature(pkey, Hash(msg_magic(message)), sig)
logging.debug("Reopening OpenSSL...") size = ssl.i2o_ECPublicKey(eckey, 0)
closeLibrary() mb = ctypes.create_string_buffer(size)
openLibrary() ssl.i2o_ECPublicKey(eckey, ctypes.byref(ctypes.pointer(mb)))
return pub pub = mb.raw
if time.time() - ssl.time_opened > 60 * 5: # Reopen every 5 min
logging.debug("Reopening OpenSSL...")
closeLibrary()
openLibrary()
return pub
def test(): def test():
sign = "HGbib2kv9gm9IJjDt1FXbXFczZi35u0rZR3iPUIt5GglDDCeIQ7v8eYXVNIaLoJRI4URGZrhwmsYQ9aVtRTnTfQ=" sign = "HGbib2kv9gm9IJjDt1FXbXFczZi35u0rZR3iPUIt5GglDDCeIQ7v8eYXVNIaLoJRI4URGZrhwmsYQ9aVtRTnTfQ="
pubkey = "044827c756561b8ef6b28b5e53a000805adbf4938ab82e1c2b7f7ea16a0d6face9a509a0a13e794d742210b00581f3e249ebcc705240af2540ea19591091ac1d41" pubkey = "044827c756561b8ef6b28b5e53a000805adbf4938ab82e1c2b7f7ea16a0d6face9a509a0a13e794d742210b00581f3e249ebcc705240af2540ea19591091ac1d41"
assert getMessagePubkey("hello", sign).encode("hex") == pubkey assert getMessagePubkey("hello", sign).encode("hex") == pubkey
test() # Make sure it working right test() # Make sure it working right
if __name__ == "__main__": if __name__ == "__main__":
import time, os, sys import time
sys.path.append("..") import os
from pybitcointools import bitcoin as btctools import sys
print "OpenSSL version %s" % openssl_version sys.path.append("..")
priv = "5JsunC55XGVqFQj5kPGK4MWgTL26jKbnPhjnmchSNPo75XXCwtk" from pybitcointools import bitcoin as btctools
address = "1N2XWu5soeppX2qUjvrf81rpdbShKJrjTr" print "OpenSSL version %s" % openssl_version
sign = btctools.ecdsa_sign("hello", priv) # HGbib2kv9gm9IJjDt1FXbXFczZi35u0rZR3iPUIt5GglDDCeIQ7v8eYXVNIaLoJRI4URGZrhwmsYQ9aVtRTnTfQ= priv = "5JsunC55XGVqFQj5kPGK4MWgTL26jKbnPhjnmchSNPo75XXCwtk"
address = "1N2XWu5soeppX2qUjvrf81rpdbShKJrjTr"
sign = btctools.ecdsa_sign("hello", priv) # HGbib2kv9gm9IJjDt1FXbXFczZi35u0rZR3iPUIt5GglDDCeIQ7v8eYXVNIaLoJRI4URGZrhwmsYQ9aVtRTnTfQ=
s = time.time() s = time.time()
for i in range(100): for i in range(100):
pubkey = getMessagePubkey("hello", sign) pubkey = getMessagePubkey("hello", sign)
verified = btctools.pubkey_to_address(pubkey) == address verified = btctools.pubkey_to_address(pubkey) == address
print "100x Verified", verified, time.time()-s print "100x Verified", verified, time.time() - s