Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Joric/bitcoin-dev, june 2012, public domain
- import hashlib
- import ctypes
- import ctypes.util
- ssl = ctypes.cdll.LoadLibrary (ctypes.util.find_library ('ssl') or 'libeay32')
- 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 KEY:
- def __init__(self):
- NID_secp256k1 = 714
- self.k = ssl.EC_KEY_new_by_curve_name(NID_secp256k1)
- self.compressed = False
- self.POINT_CONVERSION_COMPRESSED = 2
- self.POINT_CONVERSION_UNCOMPRESSED = 4
- def __del__(self):
- if ssl:
- ssl.EC_KEY_free(self.k)
- self.k = None
- def generate(self, secret=None):
- if 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()
- 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 get_secret(self):
- bn = ssl.EC_KEY_get0_private_key(self.k);
- bytes = (ssl.BN_num_bits(bn) + 7) / 8
- mb = ctypes.create_string_buffer(bytes)
- n = ssl.BN_bn2bin(bn, mb);
- return mb.raw.rjust(32, chr(0))
- def set_compressed(self, compressed):
- self.compressed = compressed
- if compressed:
- form = self.POINT_CONVERSION_COMPRESSED
- else:
- form = self.POINT_CONVERSION_UNCOMPRESSED
- ssl.EC_KEY_set_conv_form(self.k, form)
- def dhash(s):
- return hashlib.sha256(hashlib.sha256(s).digest()).digest()
- def rhash(s):
- h1 = hashlib.new('ripemd160')
- h1.update(hashlib.sha256(s).digest())
- return h1.digest()
- b58_digits = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
- def base58_encode(n):
- l = []
- while n > 0:
- n, r = divmod(n, 58)
- l.insert(0,(b58_digits[r]))
- return ''.join(l)
- def base58_decode(s):
- n = 0
- for ch in s:
- n *= 58
- digit = b58_digits.index(ch)
- n += digit
- return n
- def base58_encode_padded(s):
- res = base58_encode(int('0x' + s.encode('hex'), 16))
- pad = 0
- for c in s:
- if c == chr(0):
- pad += 1
- else:
- break
- return b58_digits[0] * pad + res
- def base58_decode_padded(s):
- pad = 0
- for c in s:
- if c == b58_digits[0]:
- pad += 1
- else:
- break
- h = '%x' % base58_decode(s)
- if len(h) % 2:
- h = '0' + h
- res = h.decode('hex')
- return chr(0) * pad + res
- def base58_check_encode(s, version=0):
- vs = chr(version) + s
- check = dhash(vs)[:4]
- return base58_encode_padded(vs + check)
- def base58_check_decode(s, version=0):
- k = base58_decode_padded(s)
- v0, data, check0 = k[0], k[1:-4], k[-4:]
- check1 = dhash(v0 + data)[:4]
- if check0 != check1:
- raise BaseException('checksum error')
- if version != ord(v0):
- raise BaseException('version mismatch')
- return data
- def gen_eckey(passphrase=None, secret=None, pkey=None, compressed=False, rounds=1):
- k = KEY()
- if passphrase:
- secret = passphrase.encode('utf8')
- for i in xrange(rounds):
- secret = hashlib.sha256(secret).digest()
- if pkey:
- secret = base58_check_decode(pkey, 128)
- compressed = len(secret) == 33
- secret = secret[0:32]
- k.generate(secret)
- k.set_compressed(compressed)
- return k
- def get_addr(k):
- pubkey = k.get_pubkey()
- secret = k.get_secret()
- hash160 = rhash(pubkey)
- addr = base58_check_encode(hash160)
- payload = secret
- if k.compressed:
- payload = secret + chr(1)
- pkey = base58_check_encode(payload, 128)
- return addr, pkey
- def test():
- # random uncompressed
- print get_addr(gen_eckey())
- # random compressed
- print get_addr(gen_eckey(compressed=True))
- # by secret
- print get_addr(gen_eckey(secret=('%064x' % 0xdeadbabe).decode('hex')))
- # by passphrase
- print get_addr(gen_eckey(passphrase='Satoshi Nakamoto'))
- # by private key, uncompressed
- print get_addr(gen_eckey(pkey='5K1HkbYffstTZDuV4riUWMbAMkQh57b8798uoy9pXYUDYeUHe7F'))
- # by private key, compressed
- print get_addr(gen_eckey(pkey='L3ATL5R9Exe1ubuAnHVgNgTKZEUKkDvWYAWkLUCyyvzzxRjtgyFe'))
- if __name__ == '__main__':
- test()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement