Last active
December 12, 2018 04:43
-
-
Save cvasqxz/fe5f5bb594fa5623846948f4bfc26f96 to your computer and use it in GitHub Desktop.
Generación de dirección MultiSig N-of-M
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
from binascii import a2b_hex | |
from hashlib import new | |
from collections import deque | |
from os import urandom | |
from argparse import ArgumentParser | |
# opcode | |
OP_CHECKMULTISIG = 'ae' | |
# Arguments | |
p = ArgumentParser(description='Creación de dirección MultiSig N-of-M') | |
p.add_argument('N', help='N: Firmas necesarias', type=int) | |
p.add_argument('M', help='M: Número de llaves privadas a generar', type=int) | |
args = p.parse_args() | |
# SHA256(SHA256(string)) | |
def doubleSHA256(s): | |
return new('sha256', new('sha256', a2b_hex(s)).digest()).hexdigest() | |
# RIPEMD160(SHA256(string)) | |
def hash160(s): | |
return new('ripemd160', new('sha256', a2b_hex(s)).digest()).hexdigest() | |
# https://github.com/joeblackwaslike/base58chec | |
def b58check(val): | |
charset = b'123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' | |
output = b'' | |
p, acc = 1, 0 | |
base = len(charset) | |
if base == 58: | |
pad_len = len(val) | |
val = val.lstrip(b'\0') | |
pad_len -= len(val) | |
for char in deque(reversed(val)): | |
acc += p * char | |
p = p << 8 | |
while acc: | |
acc, idx = divmod(acc, base) | |
output = charset[idx:idx+1] + output | |
prefix = bytes([charset[0]]) * pad_len | |
return prefix + output | |
# https://bitcoin.stackexchange.com/a/59806 | |
def secp256k1(s): | |
G = (55066263022277343669578718895168534326250603453777594175500187360389116729240, | |
32670510020758816978083085130507043184471273380659243275938904335757337482424) | |
N = 115792089237316195423570985008687907852837564279074904382605163141518161494337 | |
P = 2**256 - 2**32 - 2**9 - 2**8 - 2**7 - 2**6 - 2**4 - 1 | |
sk = int(s, 16) | |
def add(p, q): | |
px, py = p | |
qx, qy = q | |
if p == q: | |
lam = (3 * px * px) * pow(2 * py, P - 2, P) | |
else: | |
lam = (qy - py) * pow(qx - px, P - 2, P) | |
rx = lam**2 - px - qx | |
ry = lam * (px - rx) - py | |
return rx % P, ry % P | |
ret = None | |
for i in range(256): | |
if sk & (1 << i): | |
if ret is None: | |
ret = G | |
else: | |
ret = add(ret, G) | |
G = add(G, G) | |
return '04' + '{:064x}'.format(ret[0]) + '{:064x}'.format(ret[1]) | |
# create opcode OP_1 to OP_16 | |
def get_OP(n): | |
if 0 < n <= 16: | |
return hex(80 + n)[2:] | |
# create opcode OP_PUSHDATA | |
def get_hexlen(string): | |
# fixed-length hex(len(string)) | |
return '{:02x}'.format(int(len(string)/2)) | |
# P2SH address | |
def get_P2SH_addr(s): | |
# Chaucha SCRIPT_PREFIX = 50 (0x32) | |
p2sh_prefix = '32' | |
# base58check(prefix + sha160(redeemscript) + checksum) | |
scripthash = hash160(s) | |
checksum = doubleSHA256(p2sh_prefix + scripthash)[:8] | |
p2sh_addr = b58check(a2b_hex(p2sh_prefix + scripthash + checksum)) | |
return p2sh_addr.decode('utf-8') | |
def main(): | |
# N of M multisig Address | |
N = args.N | |
M = args.M | |
print('> GENERATING %s-TO-%s MULTISIG ADDRESS !!' % (N, M)) | |
# create private keys | |
privkeys = [] | |
for i in range(M): | |
privkey = new('sha256', urandom(N*M*i)).hexdigest() | |
privkeys.append(privkey) | |
# get P2SH redeem script | |
# (OP_N + OP_PUSHDATA + <pubkeys> + OP_M + OP_CHECKMULTISIG) | |
redeemScript = get_OP(N) | |
for i in privkeys: | |
pubkey = secp256k1(i) | |
redeemScript += get_hexlen(pubkey) + pubkey | |
redeemScript += get_OP(M) + OP_CHECKMULTISIG | |
# get P2SH address | |
addr = get_P2SH_addr(redeemScript) | |
# logger | |
print('> MULTISIG ADDRESS: %s' % addr) | |
print('> REDEEM SCRIPT: %s' % redeemScript) | |
for i in range(len(privkeys)): | |
print('> PRIVKEY #%i: %s' % (i+1, privkeys[i])) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment