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)
    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)
Esempio n. 3
0
 def pub_key(self):
     if self.y & 1:  # odd root
         return PublicKey(_bytes=int_to_bytes(self.x).rjust(32, b'\x00'),
                          compressed=3)
     else:  # even root
         return PublicKey(_bytes=int_to_bytes(self.x).rjust(32, b'\x00'),
                          compressed=2)
Esempio n. 4
0
 def encode(self, compressed=True) -> bytes:
     if compressed:
         if self.y & 1:  # odd root
             return b'\x03' + int_to_bytes(self.x).rjust(32, b'\x00')
         else:  # even root
             return b'\x02' + int_to_bytes(self.x).rjust(32, b'\x00')
     return b'\x04' + int_to_bytes(self.x).rjust(
         32, b'\x00') + int_to_bytes(self.y).rjust(32, b'\x00')
Esempio n. 5
0
    def encode(self, compact=False):
        """https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#der-encoding"""
        r = int_to_bytes(self.r)
        if r[0] > 0x7f:
            r = b'\x00' + r
        s = int_to_bytes(self.s)

        if s[0] > 0x7f:
            s = b'\x00' + s

        len_r = int_to_bytes(len(r))
        len_s = int_to_bytes(len(s))
        len_sig = int_to_bytes(len(r) + len(s) + 4)
        if compact:
            return r + s
        return b'\x30' + len_sig + b'\x02' + len_r + r + b'\x02' + len_s + s
Esempio n. 6
0
def decode(b58: str) -> bytes:
    partial_sum = 0
    exponent = 0
    for digit in reversed(b58):
        try:
            partial_sum += ALPHABET.index(digit) * BASE**exponent
        except ValueError:
            raise Base58DecodeError('Bad Byte') from None
        exponent += 1
    return int_to_bytes(partial_sum)
Esempio n. 7
0
 def from_binary(cls, b):
     return cls(int_to_bytes(int(b, 2)))
Esempio n. 8
0
 def from_int(cls, i):
     return cls(int_to_bytes(i))
Esempio n. 9
0
 def from_json(cls, data: dict):
     _bytes, _compressed = data.values()
     return WitPublicKey.from_hex(
         bytes_to_hex((int_to_bytes(_compressed) +
                       bytes(_bytes).rjust(32, b'\x00'))))
Esempio n. 10
0
 def pb_bytes(self) -> bytes:
     return pb_field(field_number=1,
                     tag=LENGTH_DELIMITED,
                     value=concat(
                         [int_to_bytes(self.compressed), self._bytes]))