Exemple #1
0
 def __mul__(self, e):
     e %= self.order()
     if e == 0:
         return self._infinity
     pubkey = create_string_buffer(65)
     libsecp256k1.secp256k1_ec_pubkey_create(libsecp256k1.ctx, pubkey, c_char_p(to_bytes_32(e)))
     pubkey_size = c_size_t(65)
     pubkey_serialized = create_string_buffer(65)
     libsecp256k1.secp256k1_ec_pubkey_serialize(
         libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey, SECP256K1_EC_UNCOMPRESSED)
     x = from_bytes_32(pubkey_serialized[1:33])
     y = from_bytes_32(pubkey_serialized[33:])
     return self.Point(x, y)
Exemple #2
0
    def from_text(class_, text, is_compressed=True):
        """
        This function will accept a BIP0032 wallet string, a WIF, or a bitcoin address.

        The "is_compressed" parameter is ignored unless a public address is passed in.
        """

        data = a2b_hashed_base58(text)
        netcode, key_type = netcode_and_type_for_data(data)
        data = data[1:]

        if key_type in ("pub32", "prv32"):
            # TODO: fix this... it doesn't belong here
            from pycoin.key.BIP32Node import BIP32Node
            return BIP32Node.from_wallet_key(text)

        if key_type == 'wif':
            is_compressed = (len(data) > 32)
            if is_compressed:
                data = data[:-1]
            return Key(
                secret_exponent=from_bytes_32(data),
                prefer_uncompressed=not is_compressed, netcode=netcode)
        if key_type == 'address':
            return Key(hash160=data, is_compressed=is_compressed, netcode=netcode)
        raise EncodingError("unknown text: %s" % text)
Exemple #3
0
def initial_key_to_master_key(initial_key):
    """
    initial_key:
        a hex string of length 32
    """
    b = initial_key.encode("utf8")
    orig_input = b
    for i in range(100000):
        b = hashlib.sha256(b + orig_input).digest()
    return from_bytes_32(b)
Exemple #4
0
 def sign(self, h):
     """
     Return a der-encoded signature for a hash h.
     Will throw a RuntimeError if this key is not a private key
     """
     if not self.is_private():
         raise RuntimeError("Key must be private to be able to sign")
     val = from_bytes_32(h)
     r, s = secp256k1_generator.sign(self.secret_exponent(), val)
     return sigencode_der(r, s)
Exemple #5
0
    def __init__(self, colormap, config):
        """Create a deterministic wallet address manager given
        a color map <colormap> and a configuration <config>.
        Note address manager configuration is in the key "hdwam".
        """
        self.config = config
        self.testnet = config.get('testnet', False)
        self.colormap = colormap
        self.addresses = []

        # initialize the wallet manager if this is the first time
        #  this will generate a master key.
        params = config.get('hdwam', None)
        if params is None:
            params = self.init_new_wallet()

        # master key is stored in a separate config entry
        self.master_key = config['hdw_master_key']
        master = hashlib.sha512(self.master_key.decode('hex')).digest()
        self.pycoin_wallet = BIP32Node(
            netcode='BTC', chain_code=master[32:],
            secret_exponent=from_bytes_32(master[:32])
        )

        self.genesis_color_sets = params['genesis_color_sets']
        self.color_set_states = params['color_set_states']

        # import the genesis addresses
        for i, color_desc_list in enumerate(self.genesis_color_sets):
            addr = self.get_genesis_address(i)
            addr.color_set = ColorSet(self.colormap,
                                      color_desc_list)
            self.addresses.append(addr)

        # now import the specific color addresses
        for color_set_st in self.color_set_states:
            color_desc_list = color_set_st['color_set']
            max_index = color_set_st['max_index']
            color_set = ColorSet(self.colormap, color_desc_list)
            params = {
                'testnet': self.testnet,
                'pycoin_wallet': self.pycoin_wallet,
                'color_set': color_set
                }
            for index in xrange(max_index + 1):
                params['index'] = index
                self.addresses.append(BIP0032AddressRecord(**params))

        # import the one-off addresses from the config
        for addr_params in config.get('addresses', []):
            addr_params['testnet'] = self.testnet
            addr_params['color_set'] = ColorSet(self.colormap,
                                                addr_params['color_set'])
            address = LooseAddressRecord(**addr_params)
            self.addresses.append(address)
Exemple #6
0
    def sign(self, secret_exponent, val, gen_k=None):
        nonce_function = None
        if gen_k is not None:
            k_as_bytes = to_bytes_32(gen_k(self.order(), secret_exponent, val))

            def adaptor(nonce32_p, msg32_p, key32_p, algo16_p, data, attempt):
                nonce32_p.contents[:] = k_as_bytes
                return 1
            p_b32 = POINTER(c_byte*32)
            nonce_function = CFUNCTYPE(c_int, p_b32, p_b32, p_b32, POINTER(c_byte*16), c_void_p, c_uint)(adaptor)

        sig = create_string_buffer(64)
        sig_hash_bytes = to_bytes_32(val)
        libsecp256k1.secp256k1_ecdsa_sign(
            libsecp256k1.ctx, sig, sig_hash_bytes, to_bytes_32(secret_exponent), nonce_function, None)
        compact_signature = create_string_buffer(64)
        libsecp256k1.secp256k1_ecdsa_signature_serialize_compact(libsecp256k1.ctx, compact_signature, sig)
        r = from_bytes_32(compact_signature[:32])
        s = from_bytes_32(compact_signature[32:])
        return (r, s)
Exemple #7
0
    def multiply(self, p, e):
        """Multiply a point by an integer."""
        e %= self.order()
        if p == self._infinity or e == 0:
            return self._infinity
        pubkey = create_string_buffer(64)
        public_pair_bytes = b'\4' + to_bytes_32(p[0]) + to_bytes_32(p[1])
        r = libsecp256k1.secp256k1_ec_pubkey_parse(
            libsecp256k1.ctx, pubkey, public_pair_bytes, len(public_pair_bytes))
        if not r:
            return False
        r = libsecp256k1.secp256k1_ec_pubkey_tweak_mul(libsecp256k1.ctx, pubkey, to_bytes_32(e))
        if not r:
            return self._infinity

        pubkey_serialized = create_string_buffer(65)
        pubkey_size = c_size_t(65)
        libsecp256k1.secp256k1_ec_pubkey_serialize(
            libsecp256k1.ctx, pubkey_serialized, byref(pubkey_size), pubkey, SECP256K1_EC_UNCOMPRESSED)
        x = from_bytes_32(pubkey_serialized[1:33])
        y = from_bytes_32(pubkey_serialized[33:])
        return self.Point(x, y)
Exemple #8
0
    def __init__(self, initial_key=None, master_private_key=None, master_public_key=None, netcode='BTC'):
        if [initial_key, master_private_key, master_public_key].count(None) != 2:
            raise ValueError(
                "exactly one of initial_key, master_private_key, master_public_key must be non-None")
        self._initial_key = initial_key
        self._netcode = netcode

        if initial_key is not None:
            master_private_key = initial_key_to_master_key(initial_key)
        pp = None
        if master_public_key:
            pp = tuple(from_bytes_32(master_public_key[idx:idx+32]) for idx in (0, 32))
        super(ElectrumWallet, self).__init__(secret_exponent=master_private_key, public_pair=pp)
        self._master_public_key = None
Exemple #9
0
    def __init__(self, **kwargs):
        """Create a LooseAddressRecord for a given wallet <model>,
        color <color_set> and address <address_data>. Also let the constructor
        know whether it's on <testnet> (optional).
        <address_data> is the privKey in base58 format
        """
        super(LooseAddressRecord, self).__init__(**kwargs)

        bin_privkey = a2b_hashed_base58(kwargs['address_data'])
        key_type = bin_privkey[0]
        if key_type != self.prefix:
            raise InvalidAddressError
                
        self.rawPrivKey = from_bytes_32(bin_privkey[1:])
        self.publicPoint = BasePoint * self.rawPrivKey
        self.address = public_pair_to_bitcoin_address(
            self.publicPoint.pair(), compressed=False, is_test=self.testnet)
Exemple #10
0
    def __init__(self, **kwargs):
        """Create an address for this color <color_set>
        and index <index> with the master key <master_key>.
        The address record returned for the same three variables
        will be the same every time, hence "deterministic".
        """
        super(DeterministicAddressRecord, self).__init__(**kwargs)

        if len(self.color_set.get_data()) == 0:
            color_string = "genesis block"
        else:
            color_string = self.color_set.get_hash_string()

        self.index = kwargs.get('index')
        h = hmac.new(str(kwargs['master_key']),
                     "%s|%s" % (color_string, self.index), hashlib.sha256)
        string = h.digest()
        self.rawPrivKey = from_bytes_32(string)
        self.publicPoint = BasePoint * self.rawPrivKey
        self.address = public_pair_to_bitcoin_address(self.publicPoint.pair(),
                                                      compressed=False,
                                                      is_test=self.testnet)
Exemple #11
0
 def verify(self, h, sig):
     """
     Return whether a signature is valid for hash h using this key.
     """
     val = from_bytes_32(h)
     pubkey = self.public_pair()
     rs = sigdecode_der(sig)
     if self.public_pair() is None:
         # find the pubkey from the signature and see if it matches
         # our key
         possible_pubkeys = secp256k1_generator.possible_public_pairs_for_signature(val, rs)
         hash160 = self.hash160()
         for candidate in possible_pubkeys:
             if hash160 == public_pair_to_hash160_sec(candidate, True):
                 pubkey = candidate
                 break
             if hash160 == public_pair_to_hash160_sec(candidate, False):
                 pubkey = candidate
                 break
         else:
             # signature is using a pubkey that's not this key
             return False
     return secp256k1_generator.verify(pubkey, val, rs)
Exemple #12
0
 def subkey(self, path):
     """
     path:
         of the form "K" where K is an integer index, or "K/N" where N is usually
         a 0 (deposit address) or 1 (change address)
     """
     t = path.split("/")
     if len(t) == 2:
         n, for_change = t
     else:
         n, = t
         for_change = 0
     b = (str(n) + ':' + str(for_change) + ':').encode("utf8") + self.master_public_key()
     offset = from_bytes_32(double_sha256(b))
     if self.master_private_key():
         return Key(
             secret_exponent=((self.master_private_key() + offset) % ORDER),
             prefer_uncompressed=True
         )
     p1 = offset * ecdsa.generator_secp256k1
     x, y = self.public_pair()
     p2 = ecdsa.Point(ecdsa.generator_secp256k1.curve(), x, y, ORDER)
     p = p1 + p2
     return Key(public_pair=p.pair(), prefer_uncompressed=True)
Exemple #13
0
 def public_pair(self):
     if self._public_pair is None:
         mpk = self.master_public_key()
         self._public_pair = tuple(
             from_bytes_32(mpk[idx:idx + 32]) for idx in (0, 32))
     return self._public_pair
Exemple #14
0
def generate_ecc_signature(content, key):
    key = Key(secret_exponent=from_bytes_32(a2b_hex(key)))
    return b2a_hex(key.sign(double_hash256(content))).decode()
Exemple #15
0
 def signature_for_hash_type_segwit(self, script, tx_in_idx, hash_type):
     return from_bytes_32(double_sha256(self.segwit_signature_preimage(script, tx_in_idx, hash_type)))
Exemple #16
0
    def signature_hash(self, tx_out_script, unsigned_txs_out_idx, hash_type):
        """
        Return the canonical hash for a transaction. We need to
        remove references to the signature, since it's a signature
        of the hash before the signature is applied.

        tx_out_script: the script the coins for unsigned_txs_out_idx are coming from
        unsigned_txs_out_idx: where to put the tx_out_script
        hash_type: one of SIGHASH_NONE, SIGHASH_SINGLE, SIGHASH_ALL,
        optionally bitwise or'ed with SIGHASH_ANYONECANPAY
        """

        # In case concatenating two scripts ends up with two codeseparators,
        # or an extra one at the end, this prevents all those possible incompatibilities.
        tx_out_script = tools.delete_subscript(tx_out_script, int_to_bytes(opcodes.OP_HASH160))

        # blank out other inputs' signatures
        txs_in = [self._tx_in_for_idx(i, tx_in, tx_out_script, unsigned_txs_out_idx)
                  for i, tx_in in enumerate(self.txs_in)]
        txs_out = self.txs_out

        # Blank out some of the outputs
        if (hash_type & 0x1f) == self.SIGHASH_NONE:
            # Wildcard payee
            txs_out = []

            # Let the others update at will
            for i in range(len(txs_in)):
                if i != unsigned_txs_out_idx:
                    txs_in[i].sequence = 0

        elif (hash_type & 0x1f) == self.SIGHASH_SINGLE:
            # This preserves the ability to validate existing legacy
            # transactions which followed a buggy path in Satoshi's
            # original code; note that higher level functions for signing
            # new transactions (e.g., is_signature_ok and sign_tx_in)
            # check to make sure we never get here (or at least they
            # should)
            if unsigned_txs_out_idx >= len(txs_out):
                # This should probably be moved to a constant, but the
                # likelihood of ever getting here is already really small
                # and getting smaller
                return (1 << 248)

            # Only lock in the TransactionOut payee at same index as TransactionIn; delete
            # any outputs after this one and set all outputs before this
            # one to "null" (where "null" means an empty script and a
            # value of -1)
            txs_out = [self.TransactionOut(0xffffffffffffffff, b'')] * unsigned_txs_out_idx
            txs_out.append(self.txs_out[unsigned_txs_out_idx])

            # Let the others update at will
            for i in range(len(self.txs_in)):
                if i != unsigned_txs_out_idx:
                    txs_in[i].sequence = 0

        # Blank out other inputs completely, not recommended for open transactions
        if hash_type & self.SIGHASH_ANYONECANPAY:
            txs_in = [txs_in[unsigned_txs_out_idx]]

        tmp_tx = self.__class__(self.version, txs_in, txs_out, self.lock_time)
        return from_bytes_32(tmp_tx.hash(hash_type=hash_type))
Exemple #17
0
def test_generate(mode, pdf, dev, cap_menu, pick_menu_item, goto_home, cap_story, need_keypress, microsd_path):
    # test UX and operation of the 'bitcoin core' wallet export
    mx = "Don't make PDF"

    goto_home()
    pick_menu_item('Advanced')
    try:
        pick_menu_item('Paper Wallets')
    except:
        raise pytest.skip('Feature absent')

    time.sleep(0.1)
    title, story = cap_story()

    assert 'pick a random' in story
    assert 'MANY RISKS' in story

    need_keypress('y')

    time.sleep(0.1)
    if mode == 'segwit':
        pick_menu_item('Classic Address')
        pick_menu_item('Segwit/Bech32')
        time.sleep(0.5)

    if pdf:
        assert mx in cap_menu()
        shutil.copy('../docs/paperwallet.pdf', microsd_path('paperwallet.pdf'))
        pick_menu_item(mx)
        need_keypress('y')

        time.sleep(0.1)
        title, story = cap_story()
        assert 'Pick PDF' in story

        pick_menu_item('paperwallet.pdf')


    pick_menu_item('GENERATE WALLET')

    time.sleep(0.1)
    title, story = cap_story()

    assert 'Created file' in story

    story = [i for i in story.split('\n') if i]
    if not pdf:
        fname = story[-1]
    else:
        fname = story[-2]
        pdf_name = story[-1]
        assert pdf_name.endswith('.pdf')

    assert fname.endswith('.txt')

    path = microsd_path(fname)
    with open(path, 'rt') as fp:
        hdr = None
        for ln in fp:
            ln = ln.rstrip()
            if not ln: continue

            if ln[0] != ' ':
                hdr = ln
                continue

            if '█' in ln:
                continue

            val = ln.strip()
            if 'Deposit address' in hdr:
                assert val == fname.split('.', 1)[0].split('-', 1)[0]
                txt_addr = val
                if mode != 'segwit':
                    addr = Key.from_text(val)
                else:
                    hrp, data = bech32_decode(val)
                    decoded = convertbits(data[1:], 5, 8, False)[-20:]
                    assert hrp in {'tb', 'bc' }
                    addr = Key(hash160=bytes(decoded), is_compressed=True, netcode='XTN')
            elif hdr == 'Private key:':         # for QR case
                assert val == wif
            elif 'Private key' in hdr and 'WIF=Wallet' in hdr:
                wif = val
                k1 = Key.from_text(val)
            elif 'Private key' in hdr and 'Hex, 32 bytes' in hdr:
                k2 = Key(secret_exponent=from_bytes_32(a2b_hex(val)), is_compressed=True)
            elif 'Bitcoin Core command':
                assert wif in val
                assert 'importmulti' in val or 'importprivkey' in val
            else:
                print(f'{hdr} => {val}')
                raise ValueError(hdr)

        assert k1.sec() == k2.sec()
        assert k1.public_pair() == k2.public_pair()
        assert addr.address() == k1.address()

        os.unlink(path)

    if not pdf: return

    path = microsd_path(pdf_name)
    with open(path, 'rb') as fp:

        d = fp.read()
        assert wif.encode('ascii') in d
        assert txt_addr.encode('ascii') in d

        os.unlink(path)
Exemple #18
0
 def public_pair(self):
     if self._public_pair is None:
         mpk = self.master_public_key()
         self._public_pair = tuple(from_bytes_32(mpk[idx:idx+32]) for idx in (0, 32))
     return self._public_pair
Exemple #19
0
def octetStringtoInteger(octetstring):
    ## use pycoin.encoding to translate for now
    return from_bytes_32(octetstring)
Exemple #20
0
 def test_raw_to_address(self):
     privkey = from_bytes_32(a2b_hashed_base58(self.address)[1:])
     pubkey = BasePoint * privkey
     raw = public_pair_to_hash160_sec(pubkey.pair(), False)
     addr = self.ccc.raw_to_address(raw)
     self.assertEqual(addr,'1CC3X2gu58d6wXUWMffpuzN9JAfTUWu4Kj')