Example #1
0
    def deserialize(cls, bts: bytes, network='btc'):
        def read(n):
            nonlocal bts
            data, bts = bts[:n], bts[n:]
            return data

        net = read(4)
        is_private = net in get_network_attr('extended_prv', network).values()
        is_public = net in get_network_attr('extended_pub', network).values()
        assert is_public ^ is_private, f'Invalid network bytes : {bytes_to_hex(net)}'
        address_lookup = {val: key for key, val in (
            get_network_attr('extended_prv', network) if is_private else get_network_attr('extended_pub',
                                                                                          network)).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 = PrivateKey(key, network=network) if is_private else PublicKey.decode(key, network=network)
        assert not bts, 'Leftover bytes'
        return constructor(key, code, depth=depth, i=i, parent=fingerprint, path=path, address_type=address_lookup[net])
Example #2
0
    def from_seed(seed: Union[bytes, str], address_type='P2PKH', network='btc') -> 'XPrv':
        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=b"Bitcoin seed", 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) > DefaultCurve.order:
            raise KeyDerivationError

        key, code = PrivateKey(I_L, network=network), I_R
        return XPrv(key, code, address_type=address_type)
Example #3
0
    def decode(key: bytes, network='btc'):  # TODO Easier implementation
        if key.startswith(b'\x04'):  # uncompressed key
            assert len(
                key) == 65, 'An uncompressed public key must be 65 bytes long'
            x, y = bytes_to_int(key[1:33]), bytes_to_int(key[33:])
        else:  # compressed key
            assert len(
                key) == 33, 'A compressed public key must be 33 bytes long'
            x = bytes_to_int(key[1:])
            root = modsqrt(f(x), DefaultCurve.curve.p())
            if key.startswith(b'\x03'):  # odd root
                y = root if root % 2 == 1 else -root % DefaultCurve.curve.p()
            elif key.startswith(b'\x02'):  # even root
                y = root if root % 2 == 0 else -root % DefaultCurve.curve.p()
            else:
                assert False, 'Wrong key format'

        return PublicKey(ecdsa_point_creator(x, y), network=network)
Example #4
0
    def child(self, i) -> 'XPrv':
        hardened = i >= 1 << 31

        if hardened:
            I = hmac.new(
                key=self.code,
                msg=self.key_data() + int_to_bytes(i).rjust(4, b'\x00'),
                digestmod=hashlib.sha512
            ).digest()
        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()

        I_L, I_R = bytes_to_int(I[:32]), I[32:]
        key = (I_L + self.key.int()) % DefaultCurve.order

        if I_L >= DefaultCurve.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}'

        private = PrivateKey.from_int(key)
        private.network = self.key.network
        return XPrv(
            key=private,
            code=ret_code,
            depth=self.depth + 1,
            i=i,
            parent=self.fingerprint(),
            path=path,
            address_type=self.type.value
        )
Example #5
0
 def bin(self):
     return format(bytes_to_int(self.msg), 'b')
Example #6
0
 def int(self):
     return bytes_to_int(self.msg)