def bip32_ckd(extKey, child_index): parent = bip32_parse_xkey(extKey) depth = (int.from_bytes(parent["depth"], 'big') + 1).to_bytes(1, 'big') if parent["vbytes"] in PRIVATE: network = PRIVATE.index(parent["vbytes"]) parent_prvkey = int.from_bytes(parent["key"][1:], 'big') P = pointMultiply(parent_prvkey, G) parent_pubkey = (b'\x02' if (P[1] % 2 == 0) else b'\x03') + P[0].to_bytes( 32, 'big') else: network = PUBLIC.index(parent["vbytes"]) parent_pubkey = parent["key"] fingerprint = h160(parent_pubkey)[:4] index = child_index.to_bytes(4, 'big') if (index[0] >= 0x80): #private (hardened) derivation assert parent[ "vbytes"] in PRIVATE, "Cannot do private (hardened) derivation from Pubkey" parent_key = parent["key"] else: parent_key = parent_pubkey hashValue = HMAC(parent["chain_code"], parent_key + index, sha512).digest() chain_code = hashValue[32:] p = int(hashValue[:32].hex(), 16) if parent["vbytes"] in PRIVATE: p = (p + parent_prvkey) % order p_bytes = b'\x00' + p.to_bytes(32, 'big') return bip32_compose_xkey(PRIVATE[network], depth, fingerprint, index, chain_code, p_bytes) else: P = pointMultiply(p, G) X = int.from_bytes(parent_pubkey[1:], 'big') Y_2 = X**3 + a * X + b Y = modular_sqrt(Y_2, prime) if (Y % 2 == 0): if (parent_pubkey[0] == 3): Y = prime - Y else: if (parent_pubkey[0] == 2): Y = prime - Y parentPoint = (X, Y) P = pointAdd(P, parentPoint) P_bytes = (b'\x02' if (P[1] % 2 == 0) else b'\x03') + P[0].to_bytes(32, 'big') return bip32_compose_xkey(PUBLIC[network], depth, fingerprint, index, chain_code, P_bytes)
def bip32_xprvtoxpub(xprv): decoded = b58decode_check(xprv) assert decoded[45] == 0, "not a private key" p = int.from_bytes(decoded[46:], 'big') P = pointMultiply(p, G) P_bytes = (b'\x02' if (P[1] % 2 == 0) else b'\x03') + P[0].to_bytes(32, 'big') network = PRIVATE.index(decoded[:4]) xpub = PUBLIC[network] + decoded[4:45] + P_bytes return b58encode_check(xpub)
# ==master ext private key== # depth: 0x00 for master nodes, 0x01 for level-1 derived keys, ... depth = b'\x00' # This is ser32(i) for i in xi = xpar/i, with xi the key being serialized. (0x00000000 if master key) child_number = b'\x00\x00\x00\x00' # the fingerprint of the parent's public key (0x00000000 if master key) fingerprint = b'\x00\x00\x00\x00' idf = depth + fingerprint + child_number # master private key, master public key, chain code hashValue = HMAC(b"Bitcoin seed", seed.to_bytes(seed_bytes, byteorder='big'), sha512).digest() p_bytes = hashValue[:32] p = int(p_bytes.hex(), 16) % order p_bytes = b'\x00' + p.to_bytes(32, byteorder='big') P = pointMultiply(p, G) P_bytes = (b'\x02' if (P[1] % 2 == 0) else b'\x03') + P[0].to_bytes(32, byteorder='big') chain_code = hashValue[32:] #extended keys ext_prv = b58encode_check(xprv + idf + chain_code + p_bytes) print("\nm") print(ext_prv) ext_pub = b58encode_check(xpub + idf + chain_code + P_bytes) print("M") print(ext_pub) assert ext_prv == "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", "failure" assert ext_pub == "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13", "failure" # ==first (0) hardened child==
# -*- coding: utf-8 -*- """ Created on Thu Oct 12 09:27:42 2017 @author: dfornaro, fametrano """ #### Deterministic Wallet (Type-1) #### from secp256k1 import order, G, modInv, pointAdd, pointMultiply from hashlib import sha256 import random # secret random number r = random.randint(0, order - 1) print('\nr =', hex(r), '\n') # number of key pairs to generate nKeys = 3 p = [0] * nKeys P = [(0, 0)] * nKeys for i in range(0, nKeys): # H(i|r) H_i_r = int(sha256((hex(i) + hex(r)).encode()).hexdigest(), 16) % order p[i] = H_i_r P[i] = pointMultiply(p[i], G) print('prKey#', i, ':\n', hex(p[i]), sep='') print('PubKey#', i, ':\n', hex(P[i][0]), '\n', hex(P[i][1]), '\n', sep='')
def private_key_to_public_key(private_key, version=0x04): p = pointMultiply(private_key) public_key = version + p[0] + p[1] return public_key
#!/usr/bin/python3 from hashlib import sha256 from secp256k1 import order, G, modInv, pointAdd, pointMultiply p = 0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 # 0 < p < order assert 0 < p, "Invalid Private Key" assert p < order, "Invalid Private Key" print("\n*** EC Private Key:") print(hex(p)) P = pointMultiply(p, G) print("*** EC Public Key (uncompressed):") print("04") print(hex(P[0])) print(hex(P[1])) print("\n*** The message to be signed") msg1 = "Paolo is afraid of ephemeral random numbers" print(msg1) print("*** The hash of the message") hstring1 = sha256(msg1.encode()).hexdigest() # Hash(msg) must be transformed into an integer modulo order: h1 = int(hstring1, 16) % order assert h1 != 0 print(" h1:", hex(h1)) print("\n*** Signature") # ephemeral key k must be kept secret and never reused !!!!!
#### Deterministic Wallet (Type-2) #### from secp256k1 import order, G, modInv, pointAdd, pointMultiply from hashlib import sha256 import random # secret master private key mp = random.randint(0, order - 1) print('\nsecret master private key:\n', hex(mp), '\n') # public random number r = random.randint(0, order - 1) print('public ephemeral key:\n', hex(r)) # Master PublicKey: MP = pointMultiply(mp, G) print('Master Public Key:\n', hex(MP[0]), '\n', hex(MP[1]), '\n') # number of key pairs to generate nKeys = 3 p = [0] * nKeys P = [(0, 0)] * nKeys # PubKeys can be calculated without using privKeys for i in range(0, nKeys): # H(i|r) H_i_r = int(sha256((hex(i) + hex(r)).encode()).hexdigest(), 16) % order P[i] = pointAdd(MP, pointMultiply(H_i_r, G)) # check that PubKeys match with privKeys for i in range(0, nKeys):
#!/usr/bin/python3 from hashlib import sha256 from secp256k1 import order, G, pointAdd, pointMultiply p = 0x18E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725 # 0 < p < order assert 0 < p, "Invalid Private Key" assert p < order, "Invalid Private Key" print("\n*** EC Private Key: ") print(hex(p)) P = pointMultiply(p, G) print("*** EC Public Key (uncompressed): ") print("04") print(hex(P[0])) print(hex(P[1])) print("\n*** The message to be signed") msg1 = "Paolo is afraid of ephemeral random numbers" print(msg1) print("*** The hash of the message") hstring1 = sha256(msg1.encode()).hexdigest() # Hash(msg) must be transformed into an integer modulo order: h1 = int(hstring1, 16) % order assert h1 != 0 print(" h1:", hex(h1)) print("\n*** Signature") # ephemeral key k must be kept secret and never reused !!!!!