Last active
March 9, 2016 23:28
-
-
Save HelloZeroNet/6af2373a1e33333eb3e8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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