Skip to content

Instantly share code, notes, and snippets.

@HelloZeroNet
Last active March 9, 2016 23:28
Show Gist options
  • Save HelloZeroNet/6af2373a1e33333eb3e8 to your computer and use it in GitHub Desktop.
Save HelloZeroNet/6af2373a1e33333eb3e8 to your computer and use it in GitHub Desktop.
#
# key.py - OpenSSL wrapper
# Source: git://github.com/joric/brutus.git
# which was forked from git://github.com/samrushing/caesure.git
#
import ctypes
import ctypes.util
ssl = ctypes.cdll.LoadLibrary (ctypes.util.find_library ('ssl') or 'libeay32')
# this specifies the curve used with ECDSA.
NID_secp256k1 = 714 # from openssl/obj_mac.h
# Thx to Sam Devlin for the ctypes magic 64-bit fix.
def check_result (val, func, args):
if val == 0:
raise ValueError
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.errcheck = check_result
class CKey:
def __init__(self):
self.POINT_CONVERSION_COMPRESSED = 2
self.POINT_CONVERSION_UNCOMPRESSED = 4
self.k = ssl.EC_KEY_new_by_curve_name(NID_secp256k1)
def __del__(self):
if ssl:
ssl.EC_KEY_free(self.k)
self.k = None
def generate(self, secret=None):
if secret:
self.prikey = secret
priv_key = ssl.BN_bin2bn(secret, 32, ssl.BN_new())
group = ssl.EC_KEY_get0_group(self.k)
pub_key = ssl.EC_POINT_new(group)
ctx = ssl.BN_CTX_new()
if not ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx):
raise ValueError("Could not derive public key from the supplied secret.")
ssl.EC_POINT_mul(group, pub_key, priv_key, None, None, ctx)
ssl.EC_KEY_set_private_key(self.k, priv_key)
ssl.EC_KEY_set_public_key(self.k, pub_key)
ssl.EC_POINT_free(pub_key)
ssl.BN_CTX_free(ctx)
return self.k
else:
return ssl.EC_KEY_generate_key(self.k)
def set_privkey(self, key):
self.mb = ctypes.create_string_buffer(key)
ssl.d2i_ECPrivateKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key))
def set_pubkey(self, key):
self.mb = ctypes.create_string_buffer(key)
ssl.o2i_ECPublicKey(ctypes.byref(self.k), ctypes.byref(ctypes.pointer(self.mb)), len(key))
def get_privkey(self):
size = ssl.i2d_ECPrivateKey(self.k, 0)
mb_pri = ctypes.create_string_buffer(size)
ssl.i2d_ECPrivateKey(self.k, ctypes.byref(ctypes.pointer(mb_pri)))
return mb_pri.raw
def get_pubkey(self):
size = ssl.i2o_ECPublicKey(self.k, 0)
mb = ctypes.create_string_buffer(size)
ssl.i2o_ECPublicKey(self.k, ctypes.byref(ctypes.pointer(mb)))
return mb.raw
def sign(self, hash):
sig_size0 = ctypes.c_uint32()
sig_size0.value = ssl.ECDSA_size(self.k)
mb_sig = ctypes.create_string_buffer(sig_size0.value)
result = ssl.ECDSA_sign(0, hash, len(hash), mb_sig, ctypes.byref(sig_size0), self.k)
assert 1 == result
return mb_sig.raw[:sig_size0.value]
def verify(self, hash, sig):
return ssl.ECDSA_verify(0, hash, len(hash), sig, len(sig), self.k) == 1
def set_compressed(self, compressed):
if compressed:
form = self.POINT_CONVERSION_COMPRESSED
else:
form = self.POINT_CONVERSION_UNCOMPRESSED
ssl.EC_KEY_set_conv_form(self.k, form)
def verifyWorking():
from pybitcointools import bitcoin
import time, hashlib
priv = "5JsunC55XGVqFQj5kPGK4MWgTL26jKbnPhjnmchSNPo75XXCwtk"
address = "1N2XWu5soeppX2qUjvrf81rpdbShKJrjTr"
sign = bitcoin.ecdsa_sign("hello", priv)
s = time.time()
for i in range(1):
pub = bitcoin.ecdsa_recover("hello", sign)
sign_address = bitcoin.pubtoaddr(pub)
print "pybitcointools verify", time.time()-s, sign
assert sign_address == address
k = CKey()
k.generate(priv)
k.set_compressed(False)
sign = k.sign("hello")
pub = k.get_pubkey()
s = time.time()
for i in range(10):
k = CKey()
k.set_pubkey(pub)
verify = k.verify("hello", sign)
assert verify
print "openssl verify", time.time()-s, sign.encode("base64"), verify
if __name__ == '__main__':
verifyWorking()
# ethalone keys
""" ec_secret = '' + \
'a0dc65ffca799873cbea0ac274015b9526505daaaed385155425f7337704883e'
ec_private = '308201130201010420' + \
'a0dc65ffca799873cbea0ac274015b9526505daaaed385155425f7337704883e' + \
'a081a53081a2020101302c06072a8648ce3d0101022100' + \
'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f' + \
'300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2d' + \
'ce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a6' + \
'8554199c47d08ffb10d4b8022100' + \
'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141' + \
'020101a14403420004' + \
'0791dc70b75aa995213244ad3f4886d74d61ccd3ef658243fcad14c9ccee2b0a' + \
'a762fbc6ac0921b8f17025bb8458b92794ae87a133894d70d7995fc0b6b5ab90'
k = CKey()
k.generate (ec_secret.decode('hex'))
k.set_compressed(True)
print("Priv", k.get_privkey().encode('hex'))
print("Pub", k.get_pubkey().encode('hex'))
# not sure this is needed any more: print k.get_secret().encode('hex')
hash = 'Hello, world!'
print(k.verify(hash, k.sign(hash)))"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment