rev194, Fix for ugly openSSL layer memory leak, memory usage test to openssl stability test
This commit is contained in:
parent
9b7c21e14d
commit
94165176d3
5 changed files with 111 additions and 53 deletions
|
@ -4,7 +4,7 @@ import ConfigParser
|
||||||
class Config(object):
|
class Config(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.version = "0.3.0"
|
self.version = "0.3.0"
|
||||||
self.rev = 193
|
self.rev = 194
|
||||||
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
|
||||||
|
|
|
@ -74,9 +74,24 @@ 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):
|
||||||
|
base, minlen = int(base), int(minlen)
|
||||||
|
code_string = ''.join([chr(x) for x in range(256)])
|
||||||
|
result = ""
|
||||||
|
while val > 0:
|
||||||
|
result = code_string[val % base] + result
|
||||||
|
val //= base
|
||||||
|
return code_string[0] * max(minlen - len(result), 0) + result
|
||||||
|
|
||||||
|
def num_to_var_int(x):
|
||||||
|
x = int(x)
|
||||||
|
if x < 253: return chr(x)
|
||||||
|
elif x < 65536: 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" + chr( len(message) ) + message
|
return "\x18Bitcoin Signed Message:\n" + num_to_var_int( len(message) ) + message
|
||||||
return "\x18Bitcoin Signed Message:\n" + chr( len(message) ) + message
|
|
||||||
|
|
||||||
def get_address(eckey):
|
def get_address(eckey):
|
||||||
size = ssl.i2o_ECPublicKey (eckey, 0)
|
size = ssl.i2o_ECPublicKey (eckey, 0)
|
||||||
|
|
|
@ -10,6 +10,8 @@ import ctypes
|
||||||
import ctypes.util
|
import ctypes.util
|
||||||
import hashlib
|
import hashlib
|
||||||
import base64
|
import base64
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
addrtype = 0
|
addrtype = 0
|
||||||
|
|
||||||
class _OpenSSL:
|
class _OpenSSL:
|
||||||
|
@ -17,6 +19,7 @@ class _OpenSSL:
|
||||||
Wrapper for OpenSSL using ctypes
|
Wrapper for OpenSSL using ctypes
|
||||||
"""
|
"""
|
||||||
def __init__(self, library):
|
def __init__(self, library):
|
||||||
|
self.time_opened = time.time()
|
||||||
"""
|
"""
|
||||||
Build the wrapper
|
Build the wrapper
|
||||||
"""
|
"""
|
||||||
|
@ -172,14 +175,23 @@ class _OpenSSL:
|
||||||
self.i2o_ECPublicKey.restype = ctypes.c_void_p
|
self.i2o_ECPublicKey.restype = ctypes.c_void_p
|
||||||
self.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, 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]
|
||||||
|
|
||||||
|
|
||||||
|
def openLibrary():
|
||||||
|
global ssl
|
||||||
|
try:
|
||||||
|
ssl = _OpenSSL("src/lib/opensslVerify/libeay32.dll")
|
||||||
|
except:
|
||||||
|
ssl = _OpenSSL(ctypes.util.find_library('ssl') or ctypes.util.find_library('crypto') or 'libeay32')
|
||||||
|
|
||||||
try:
|
openLibrary()
|
||||||
ssl = _OpenSSL("src/lib/opensslVerify/libeay32.dll")
|
|
||||||
except:
|
|
||||||
ssl = _OpenSSL(ctypes.util.find_library('ssl') or ctypes.util.find_library('crypto') or 'libeay32')
|
|
||||||
|
|
||||||
openssl_version = "%.9X" % ssl._lib.SSLeay()
|
openssl_version = "%.9X" % ssl._lib.SSLeay()
|
||||||
|
|
||||||
NID_secp256k1 = 714
|
NID_secp256k1 = 714
|
||||||
|
@ -296,51 +308,58 @@ def SetCompactSignature(pkey, hash, signature):
|
||||||
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
|
||||||
|
|
||||||
group = ssl.EC_KEY_get0_group(eckey)
|
try:
|
||||||
ctx = ssl.BN_CTX_new()
|
group = ssl.EC_KEY_get0_group(eckey)
|
||||||
ssl.BN_CTX_start(ctx)
|
ctx = ssl.BN_CTX_new()
|
||||||
order = ssl.BN_CTX_get(ctx)
|
ssl.BN_CTX_start(ctx)
|
||||||
ssl.EC_GROUP_get_order(group, order, ctx)
|
order = ssl.BN_CTX_get(ctx)
|
||||||
x = ssl.BN_CTX_get(ctx)
|
ssl.EC_GROUP_get_order(group, order, ctx)
|
||||||
ssl.BN_copy(x, order);
|
x = ssl.BN_CTX_get(ctx)
|
||||||
ssl.BN_mul_word(x, i);
|
ssl.BN_copy(x, order);
|
||||||
ssl.BN_add(x, x, r)
|
ssl.BN_mul_word(x, i);
|
||||||
field = ssl.BN_CTX_get(ctx)
|
ssl.BN_add(x, x, r)
|
||||||
ssl.EC_GROUP_get_curve_GFp(group, field, None, None, ctx)
|
field = ssl.BN_CTX_get(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
|
|
||||||
|
|
||||||
R = ssl.EC_POINT_new(group)
|
|
||||||
ssl.EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)
|
|
||||||
|
|
||||||
if check:
|
|
||||||
O = ssl.EC_POINT_new(group)
|
|
||||||
ssl.EC_POINT_mul(group, O, None, R, order, ctx)
|
|
||||||
if ssl.EC_POINT_is_at_infinity(group, O):
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
Q = ssl.EC_POINT_new(group)
|
R = ssl.EC_POINT_new(group)
|
||||||
n = ssl.EC_GROUP_get_degree(group)
|
ssl.EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)
|
||||||
e = ssl.BN_CTX_get(ctx)
|
|
||||||
ssl.BN_bin2bn(msg, msglen, e)
|
|
||||||
if 8 * msglen > n: ssl.BN_rshift(e, e, 8 - (n & 7))
|
|
||||||
|
|
||||||
zero = ssl.BN_CTX_get(ctx)
|
if check:
|
||||||
ssl.BN_set_word(zero, 0)
|
O = ssl.EC_POINT_new(group)
|
||||||
ssl.BN_mod_sub(e, zero, e, order, ctx)
|
ssl.EC_POINT_mul(group, O, None, R, order, ctx)
|
||||||
rr = ssl.BN_CTX_get(ctx);
|
if ssl.EC_POINT_is_at_infinity(group, O):
|
||||||
ssl.BN_mod_inverse(rr, r, order, ctx)
|
return False
|
||||||
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
|
|
||||||
|
|
||||||
def close():
|
Q = ssl.EC_POINT_new(group)
|
||||||
|
n = ssl.EC_GROUP_get_degree(group)
|
||||||
|
e = ssl.BN_CTX_get(ctx)
|
||||||
|
ssl.BN_bin2bn(msg, msglen, e)
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
@ -354,7 +373,12 @@ def getMessagePubkey(message, sig):
|
||||||
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 mb.raw
|
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="
|
||||||
|
|
|
@ -1,16 +1,35 @@
|
||||||
import opensslVerify, gevent, time
|
import opensslVerify, gevent, time
|
||||||
from gevent import monkey; monkey.patch_all(thread=False, ssl=False)
|
from gevent import monkey
|
||||||
|
monkey.patch_all(thread=False, ssl=False)
|
||||||
|
|
||||||
def test():
|
def test():
|
||||||
data = "A"*1024
|
data = "A"*1024
|
||||||
sign = "G2Jo8dDa+jqvJipft9E3kfrAxjESWLBpVtuGIiEBCD/UUyHmRMYNqnlWeOiaHHpja5LOP+U5CanRALfOjCSYIa8="
|
sign = "G2Jo8dDa+jqvJipft9E3kfrAxjESWLBpVtuGIiEBCD/UUyHmRMYNqnlWeOiaHHpja5LOP+U5CanRALfOjCSYIa8="
|
||||||
for i in range(5*1000):
|
for i in range(2*1000):
|
||||||
if i%1000 == 0:
|
if i%1000 == 0:
|
||||||
print i, len(data)
|
print i, len(data)
|
||||||
data += data+"A"
|
#data += data+"A"
|
||||||
time.sleep(0)
|
time.sleep(0)
|
||||||
pub = opensslVerify.getMessagePubkey(data, sign)
|
pub = opensslVerify.getMessagePubkey(data, sign)
|
||||||
|
|
||||||
print repr(pub), len(data)
|
print repr(pub), len(data)
|
||||||
|
|
||||||
gevent.joinall([gevent.spawn(test), gevent.spawn(test)])
|
while 1:
|
||||||
|
s = time.time()
|
||||||
|
gevent.joinall([gevent.spawn(test), gevent.spawn(test)])
|
||||||
|
try:
|
||||||
|
import psutil, os
|
||||||
|
process = psutil.Process(os.getpid())
|
||||||
|
print "Mem:", process.get_memory_info()[0] / float(2 ** 20)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raw_input("finished, in %.2fs, check memory usage" % (time.time()-s))
|
||||||
|
opensslVerify.close()
|
||||||
|
opensslVerify.open()
|
||||||
|
try:
|
||||||
|
import psutil, os
|
||||||
|
process = psutil.Process(os.getpid())
|
||||||
|
print "Mem:", process.get_memory_info()[0] / float(2 ** 20)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
raw_input("closed and openssl, check memory again, press enter to start again")
|
||||||
|
|
|
@ -13,7 +13,7 @@ def main():
|
||||||
# Try cleanup openssl
|
# Try cleanup openssl
|
||||||
try:
|
try:
|
||||||
if "lib.opensslVerify" in sys.modules:
|
if "lib.opensslVerify" in sys.modules:
|
||||||
sys.modules["lib.opensslVerify"].opensslVerify.close()
|
sys.modules["lib.opensslVerify"].opensslVerify.closeLibrary()
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
print "Error closing openssl", err
|
print "Error closing openssl", err
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue