rev194, Fix for ugly openSSL layer memory leak, memory usage test to openssl stability test

This commit is contained in:
HelloZeroNet 2015-05-27 16:58:36 +02:00
parent 9b7c21e14d
commit 94165176d3
5 changed files with 111 additions and 53 deletions

View File

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

View File

@ -74,9 +74,24 @@ def public_key_to_bc_address(public_key):
h160 = hash_160(public_key)
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):
#return "\x18Bitcoin Signed Message:\n" + chr( len(message) ) + message
return "\x18Bitcoin Signed Message:\n" + chr( len(message) ) + message
return "\x18Bitcoin Signed Message:\n" + num_to_var_int( len(message) ) + message
def get_address(eckey):
size = ssl.i2o_ECPublicKey (eckey, 0)

View File

@ -10,6 +10,8 @@ import ctypes
import ctypes.util
import hashlib
import base64
import time
import logging
addrtype = 0
class _OpenSSL:
@ -17,6 +19,7 @@ class _OpenSSL:
Wrapper for OpenSSL using ctypes
"""
def __init__(self, library):
self.time_opened = time.time()
"""
Build the wrapper
"""
@ -172,14 +175,23 @@ class _OpenSSL:
self.i2o_ECPublicKey.restype = 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:
ssl = _OpenSSL("src/lib/opensslVerify/libeay32.dll")
except:
ssl = _OpenSSL(ctypes.util.find_library('ssl') or ctypes.util.find_library('crypto') or 'libeay32')
openLibrary()
openssl_version = "%.9X" % ssl._lib.SSLeay()
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):
n = 0
i = recid / 2
ctx = R = O = Q = None
group = ssl.EC_KEY_get0_group(eckey)
ctx = ssl.BN_CTX_new()
ssl.BN_CTX_start(ctx)
order = ssl.BN_CTX_get(ctx)
ssl.EC_GROUP_get_order(group, order, ctx)
x = ssl.BN_CTX_get(ctx)
ssl.BN_copy(x, order);
ssl.BN_mul_word(x, i);
ssl.BN_add(x, x, r)
field = ssl.BN_CTX_get(ctx)
ssl.EC_GROUP_get_curve_GFp(group, field, None, None, ctx)
try:
group = ssl.EC_KEY_get0_group(eckey)
ctx = ssl.BN_CTX_new()
ssl.BN_CTX_start(ctx)
order = ssl.BN_CTX_get(ctx)
ssl.EC_GROUP_get_order(group, order, ctx)
x = ssl.BN_CTX_get(ctx)
ssl.BN_copy(x, order);
ssl.BN_mul_word(x, i);
ssl.BN_add(x, x, r)
field = ssl.BN_CTX_get(ctx)
ssl.EC_GROUP_get_curve_GFp(group, field, None, None, ctx)
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):
if (ssl.BN_cmp(x, field) >= 0):
return False
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))
R = ssl.EC_POINT_new(group)
ssl.EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)
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
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
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
if "FreeLibrary" in dir(_ctypes):
_ctypes.FreeLibrary(ssl._lib._handle)
@ -354,7 +373,12 @@ def getMessagePubkey(message, sig):
size = ssl.i2o_ECPublicKey (eckey, 0)
mb = ctypes.create_string_buffer (size)
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():
sign = "HGbib2kv9gm9IJjDt1FXbXFczZi35u0rZR3iPUIt5GglDDCeIQ7v8eYXVNIaLoJRI4URGZrhwmsYQ9aVtRTnTfQ="

View File

@ -1,16 +1,35 @@
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():
data = "A"*1024
sign = "G2Jo8dDa+jqvJipft9E3kfrAxjESWLBpVtuGIiEBCD/UUyHmRMYNqnlWeOiaHHpja5LOP+U5CanRALfOjCSYIa8="
for i in range(5*1000):
for i in range(2*1000):
if i%1000 == 0:
print i, len(data)
data += data+"A"
#data += data+"A"
time.sleep(0)
pub = opensslVerify.getMessagePubkey(data, sign)
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")

View File

@ -13,7 +13,7 @@ def main():
# Try cleanup openssl
try:
if "lib.opensslVerify" in sys.modules:
sys.modules["lib.opensslVerify"].opensslVerify.close()
sys.modules["lib.opensslVerify"].opensslVerify.closeLibrary()
except Exception, err:
print "Error closing openssl", err