Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # -*- Mode: Python -*-
- import ctypes
- import ctypes.util
- import hashlib
- import base64
- addrtype = 0
- ssl = ctypes.cdll.LoadLibrary (ctypes.util.find_library ('ssl') or 'libeay32')
- NID_secp256k1 = 714
- 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
- POINT_CONVERSION_COMPRESSED = 2
- POINT_CONVERSION_UNCOMPRESSED = 4
- __b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
- __b58base = len(__b58chars)
- def b58encode(v):
- """ encode v, which is a string of bytes, to base58.
- """
- long_value = 0L
- for (i, c) in enumerate(v[::-1]):
- long_value += (256**i) * ord(c)
- result = ''
- while long_value >= __b58base:
- div, mod = divmod(long_value, __b58base)
- result = __b58chars[mod] + result
- long_value = div
- result = __b58chars[long_value] + result
- # Bitcoin does a little leading-zero-compression:
- # leading 0-bytes in the input become leading-1s
- nPad = 0
- for c in v:
- if c == '\0': nPad += 1
- else: break
- return (__b58chars[0]*nPad) + result
- def hash_160(public_key):
- md = hashlib.new('ripemd160')
- md.update(hashlib.sha256(public_key).digest())
- return md.digest()
- def hash_160_to_bc_address(h160):
- vh160 = chr(addrtype) + h160
- h = Hash(vh160)
- addr = vh160 + h[0:4]
- return b58encode(addr)
- def public_key_to_bc_address(public_key):
- h160 = hash_160(public_key)
- return hash_160_to_bc_address(h160)
- def msg_magic(message):
- return "\x18Bitcoin Signed Message:\n" + chr( len(message) ) + message
- def get_address(eckey):
- size = ssl.i2o_ECPublicKey (eckey, 0)
- mb = ctypes.create_string_buffer (size)
- ssl.i2o_ECPublicKey (eckey, ctypes.byref (ctypes.pointer (mb)))
- return public_key_to_bc_address(mb.raw)
- def Hash(data):
- return hashlib.sha256(hashlib.sha256(data).digest()).digest()
- def bx(bn, size=32):
- b = ctypes.create_string_buffer(size)
- ssl.BN_bn2bin(bn, b);
- return b.raw.encode('hex')
- def verify_message(address, signature, message):
- pkey = ssl.EC_KEY_new_by_curve_name (NID_secp256k1)
- eckey = SetCompactSignature(pkey, Hash(msg_magic(message)), signature)
- addr = get_address(eckey)
- return (address == addr)
- def SetCompactSignature(pkey, hash, signature):
- sig = base64.b64decode(signature)
- if len(sig) != 65:
- raise BaseException("Wrong encoding")
- nV = ord(sig[0])
- if nV < 27 or nV >= 35:
- return False
- if nV >= 31:
- ssl.EC_KEY_set_conv_form(pkey, POINT_CONVERSION_COMPRESSED)
- nV -= 4
- r = ssl.BN_bin2bn (sig[1:33], 32, ssl.BN_new())
- s = ssl.BN_bin2bn (sig[33:], 32, ssl.BN_new())
- eckey = ECDSA_SIG_recover_key_GFp(pkey, r, s, hash, len(hash), nV - 27, False);
- return eckey
- def ECDSA_SIG_recover_key_GFp(eckey, r, s, msg, msglen, recid, check):
- n = 0
- i = recid / 2
- # print 'r', bx(r)
- # print 's', bx(s)
- # print 'd', recid
- 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):
- 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))
- print bx(e)
- 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 __name__ == '__main__':
- # some simple testing code
- print verify_message('16vqGo3KRKE9kTsTZxKoJKLzwZGTodK3ce',
- 'HPDs1TesA48a9up4QORIuub67VHBM37X66skAYz0Esg23gdfMuCTYDFORc6XGpKZ2/flJ2h/DUF569FJxGoVZ50=',
- 'test message') # good
- print verify_message('16vqGo3KRKE9kTsTZxKoJKLzwZGTodK3ce',
- 'HPDs1TesA48a9up4QORIuub67VHBM37X66skAYz0Esg23gdfMuCTYDFORc6XGpKZ2/flJ2h/DUF569FJxGoVZ50=',
- 'test message 2') # bad
- print verify_message('1GdKjTSg2eMyeVvPV5Nivo6kR8yP2GT7wF',
- 'GyMn9AdYeZIPWLVCiAblOOG18Qqy4fFaqjg5rjH6QT5tNiUXLS6T2o7iuWkV1gc4DbEWvyi8yJ8FvSkmEs3voWE=',
- 'freenode:#bitcoin-otc:b42f7e7ea336db4109df6badc05c6b3ea8bfaa13575b51631c5178a7')
- print verify_message('1Hpj6xv9AzaaXjPPisQrdAD2tu84cnPv3f','INEJxQnSu6mwGnLs0E8eirl5g+0cAC9D5M7hALHD9sK0XQ66CH9mas06gNoIX7K1NKTLaj3MzVe8z3pt6apGJ34=','testtest')
- print verify_message('18uitB5ARAhyxmkN2Sa9TbEuoGN1he83BX','IMAtT1SjRyP6bz6vm5tKDTTTNYS6D8w2RQQyKD3VGPq2i2txGd2ar18L8/nvF1+kAMo5tNc4x0xAOGP0HRjKLjc=','testtest')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement