def from_slip32(master_key: str, root_path=None) -> Xprv:
    bech = bech32_decode_address(master_key)
    idx = 0
    # byte lengths of the serialized byte data
    DEPTH = 1
    INDEX = 4 * bech[idx:idx + DEPTH][0]
    CHAIN = 32
    secret_prefix = b'\x00'
    KEYLN = 32

    depth = bech[idx:idx + DEPTH]
    idx += DEPTH
    index = None
    chain_code = bytes(bech[idx:idx + CHAIN])

    idx += CHAIN
    idx += len(secret_prefix)
    key_data = bytes(bech[idx:idx + KEYLN])
    private_key = WitPrivateKey(key_data)
    public_key = private_key.to_public()

    chain_code = bytes(bech[1:33])
    private_key = WitPrivateKey(bytes(bech[34:66]))

    return Xprv(key=private_key,
                code=chain_code,
                depth=depth[0],
                path=root_path)
    def from_xprv(cls, xprv: str) -> 'Xprv':
        ...
        from witnet.util.transformations.bech32 import bech32_decode_address

        bech = bech32_decode_address(xprv)
        idx = 0
        # byte lengths of the serialized byte data
        DEPTH = 1
        INDEX = 4 * bech[idx:idx + DEPTH][0]
        CHAIN = 32
        secret_prefix = b'\x00'
        KEYLN = 32

        depth = bech[idx:idx + DEPTH]
        idx += DEPTH
        if INDEX == 0:
            print('MasterKey')
        index = None
        chain_code = bytes(bech[idx:idx + CHAIN])

        idx += CHAIN
        idx += len(secret_prefix)
        key_data = bytes(bech[idx:idx + KEYLN])
        private_key = WitPrivateKey(key_data)
        public_key = private_key.to_public()

        chain_code = bytes(bech[1:33])
        tmp_xprv = Xprv(key=private_key, code=chain_code, depth=depth[0])
        return bech
    def child(self, i: int) -> 'Xpub':
        hardened = i >= 1 << 31

        if hardened:
            raise KeyDerivationError(
                'Cannot derive a hardened key from an extended public key')

        I = hmac.new(key=self.code,
                     msg=self.keydata() + int_to_bytes(i).rjust(4, b'\x00'),
                     digestmod=hashlib.sha512).digest()
        tmp = bytes_to_hex(self.keydata() + int_to_bytes(i).rjust(4, b'\x00'))

        I_L, I_R = I[:32], I[32:]

        key = WitPrivateKey(I_L).to_public().point + self.key.point
        ret_code = I_R
        path = self.path + f'/{i}'

        # TODO add point at infinity check
        return Xpub(WitPublicKey(key),
                    ret_code,
                    depth=self.depth + 1,
                    i=i,
                    parent=self.fingerprint(),
                    path=path)
    def child(self, i: int) -> 'Xprv':
        hardened = i >= 1 << 31
        if hardened:
            I = hmac.new(key=self.code,
                         msg=self.keydata() +
                         int_to_bytes(i).rjust(4, b'\x00'),
                         digestmod=hashlib.sha512).digest()
            tmp = int_to_bytes(i).rjust(4, b'\x00')

        else:
            I = hmac.new(key=self.code,
                         msg=self.key.to_public().encode(compressed=True) +
                         int_to_bytes(i).rjust(4, b'\x00'),
                         digestmod=hashlib.sha512).digest()
            tmp = self.key.to_public().encode(
                compressed=True) + int_to_bytes(i).rjust(4, b'\x00')

        I_L, I_R = bytes_to_int(I[:32]), I[32:]
        key = (I_L + self.key.int()) % CURVE.order
        if I_L >= CURVE.order or key == 0:
            return self.child(i + 1)
        ret_code = I_R
        if hardened:
            path = self.path + f'/{i - 2 ** 31}h'
        else:
            path = self.path + f'/{i}'

        return Xprv(WitPrivateKey.from_int(key),
                    ret_code,
                    depth=self.depth + 1,
                    i=i,
                    parent=self.fingerprint(),
                    path=path)
Beispiel #5
0
    def test_sign_and_verify(self):
        data = hex_to_bytes(concat(['ab' for _ in range(32)]))
        secret_key = WitPrivateKey.from_hex(concat(['cd' for _ in range(32)]))
        public_key = secret_key.to_public()
        local_signature = secret_key.sign_hash(data)
        expected_signature = '3044' \
                             '0220' \
                             '3dc4fa74655c21b7ffc0740e29bfd88647e8dfe2b68c507cf96264e4e7439c1f' \
                             '0220' \
                             '7aa61261b18eebdfdb704ca7bab4c7bcf7961ae0ade5309f6f1398e21aec0f9f'

        recovered_signature = Signature.from_hex(expected_signature)

        assert local_signature.verify_hash(data, public_key)
        assert recovered_signature.verify_hash(data, public_key)
 def from_seed(cls,
               seed: Union[bytes, str],
               network_key=b'Bitcoin seed') -> 'Xprv':
     """
     :param seed:
     :param network_key:
     :return:
     """
     if isinstance(seed, str):
         seed = hex_to_bytes(seed)
     assert 16 <= len(seed) <= 64, 'Seed should be between 128 and 512 bits'
     I = hmac.new(key=network_key, msg=seed,
                  digestmod=hashlib.sha512).digest()
     I_L, I_R = I[:32], I[32:]
     if bytes_to_int(I_L) == 0 or bytes_to_int(I_L) > CURVE.order:
         raise KeyDerivationError
     key, code = WitPrivateKey(I_L), I_R
     # print(f'\tMaster Secret Key: {bytes_to_hex(I_L)}')
     # print(f'\tMaster Chain Code: {bytes_to_hex(I_R)}')
     return cls(key, code)
Beispiel #7
0
    def deserialize(cls, bts: bytes) -> 'ExtendedKey':
        from witnet.crypto.hd_wallet.extended_private_key import Xprv
        from witnet.crypto.hd_wallet.extended_public_key import Xpub

        def read(n):
            nonlocal bts
            data, bts = bts[:n], bts[n:]
            return data

        net = read(4)
        is_private = net in network('Mainnet').values()
        is_public = net in network('Mainnet').values()
        assert is_public ^ is_private, f'Invalid network bytes : {bytes_to_hex(net)}'
        # address_lookup = {val: key for key, val in (network('Mainnet') if is_private else network('Mainnet')).items()}
        constructor = Xprv if is_private else Xpub
        depth = bytes_to_int(read(1))
        assert depth in range(256), f'Invalid depth : {depth}'
        fingerprint = read(4)
        i = bytes_to_int(read(4))
        if depth == 0:
            i = None
            path = None
        else:
            ih = f'{i}' if i < 2**31 else f"{i - 2 ** 31}h"
            path = '/'.join([constructor.root_path] +
                            ['x' for _ in range(depth - 1)] + [ih])

        code = read(32)
        key = read(33)
        key = WitPrivateKey(key) if is_private else WitPublicKey.decode(key)
        assert not bts, 'Leftover bytes'
        return constructor(key,
                           code,
                           depth=depth,
                           i=i,
                           parent=fingerprint,
                           path=path)
Beispiel #8
0
    def create_vtt(self, to, private_key: WitPrivateKey, change_address=None, utxo_selection_strategy=None,
                   fee: int = 0,
                   fee_type='absolute'):

        node = NodeClient.manager()
        now = datetime.timestamp(datetime.now())
        to_sum = 0
        print(self.balance)
        print(to_sum + fee)
        for receiver in to:
            to_sum += receiver['value']
        to_sum += fee
        if self.balance < nano_wit_to_wit(to_sum):
            return '0', {"error": "Insufficient Funds"}

        available_utxos, selected_utxos = {}, []
        for x, utxo in enumerate(self.utxos):
            if utxo['timelock'] < now:
                available_utxos[utxo['output_pointer']] = utxo['value']

        sorted_x = sorted(available_utxos.items(), key=lambda kv: kv[1])
        value_owed = to_sum
        selected_utxo_total_value = 0

        for i, x in enumerate(sorted_x):
            if value_owed > 0:
                selected_utxos.append(x)
                selected_utxo_total_value += x[1]
                value_owed -= x[1]

        change = int(abs(value_owed))
        if change > 0:
            to.append({'address': self.address, 'time_lock': 0, 'value': change})
            change = 0

        inputs, outputs = [], []

        # Inputs
        for utxo in selected_utxos:
            output_pointer, value = utxo
            # print(output_pointer, value)
            _input = Input.from_json({'output_pointer': output_pointer})
            inputs.append(_input)

        # Outputs
        for receiver in to:
            pkh = receiver['address']
            value = receiver['value']

            if 'time_lock' in receiver:
                time_lock = receiver['time_lock']
            else:
                time_lock = 0

            vto_dict = {
                'pkh': pkh,
                'time_lock': time_lock,
                'value': value
            }

            output: ValueTransferOutput = ValueTransferOutput.from_json(vto_dict)
            outputs.append(output)
        vtt_transaction_body = VTTransactionBody(inputs=inputs, outputs=outputs)

        vtt_hash = vtt_transaction_body.hash()
        der_bytes = private_key.sign_hash(vtt_hash).encode(compact=False)

        signatures = []
        signature = Signature(secp256k1=Secp256k1Signature(der=der_bytes))
        pubkey = private_key.to_public().pub_key()
        sig = KeyedSignature(signature=signature, public_key=pubkey)

        for _input in inputs:
            signatures.append(sig)

        vtt_transaction_body = VTTransactionBody(inputs=inputs, outputs=outputs)
        transaction = VTTransaction(body=vtt_transaction_body, signatures=signatures)
        return vtt_hash, transaction