Skip to content

Instantly share code, notes, and snippets.

@josephdunn
Created April 9, 2013 17:26
Show Gist options
  • Select an option

  • Save josephdunn/5347612 to your computer and use it in GitHub Desktop.

Select an option

Save josephdunn/5347612 to your computer and use it in GitHub Desktop.

Revisions

  1. Joseph Dunn created this gist Apr 9, 2013.
    165 changes: 165 additions & 0 deletions addrgen.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,165 @@
    #!/usr/bin/env python
    # Joric/bitcoin-dev, june 2012, public domain

    import hashlib
    import ctypes
    import ctypes.util
    import sys

    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:
    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()
    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 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 reencode(pkey):
    payload = base58_check_decode(pkey,128)
    secret = payload[:-1]
    payload = secret + chr(1)
    pkey = base58_check_encode(payload, 128)
    print pkey
    get_addr(gen_eckey(pkey))

    if __name__ == '__main__':
    print get_addr(gen_eckey(passphrase='brainz'))