Esempio n. 1
0
def point_from_pub_key(pub_key: PubKey, ec: Curve = secp256k1) -> Point:
    "Return an elliptic curve point tuple from a public key."

    if isinstance(pub_key, tuple):
        if ec.is_on_curve(pub_key) and pub_key[1] != 0:
            return pub_key
        raise BTClibValueError(f"not a valid public key: {pub_key}")
    if isinstance(pub_key, BIP32KeyData):
        return _point_from_xpub(pub_key, ec)
    try:
        return _point_from_xpub(pub_key, ec)
    except (TypeError, BTClibValueError):
        pass

    # it must be octets
    try:
        return point_from_octets(pub_key, ec)
    except (TypeError, ValueError) as e:
        raise BTClibValueError(f"not a public key: {pub_key!r}") from e
Esempio n. 2
0
def point_from_octets(pub_key: Octets, ec: Curve = secp256k1) -> Point:
    """Return a tuple (x_Q, y_Q) that belongs to the curve.

    Return a tuple (x_Q, y_Q) that belongs to the curve according to
    SEC 1 v.2, section 2.3.4.
    """

    pub_key = bytes_from_octets(pub_key, (ec.p_size + 1, 2 * ec.p_size + 1))

    bsize = len(pub_key)  # bytes
    if pub_key[0] in (0x02, 0x03):  # compressed point
        if bsize != ec.p_size + 1:
            err_msg = "invalid size for compressed point: "
            err_msg += f"{bsize} instead of {ec.p_size + 1}"
            raise BTClibValueError(err_msg)
        x_Q = int.from_bytes(pub_key[1:], byteorder="big")
        try:
            y_Q = ec.y_even(x_Q)  # also check x_Q validity
            return x_Q, y_Q if pub_key[0] == 0x02 else ec.p - y_Q
        except BTClibValueError as e:
            msg = f"invalid x-coordinate: '{hex_string(x_Q)}'"
            raise BTClibValueError(msg) from e
    elif pub_key[0] == 0x04:  # uncompressed point
        if bsize != 2 * ec.p_size + 1:
            err_msg = "invalid size for uncompressed point: "
            err_msg += f"{bsize} instead of {2 * ec.p_size + 1}"
            raise BTClibValueError(err_msg)
        x_Q = int.from_bytes(pub_key[1:ec.p_size + 1],
                             byteorder="big",
                             signed=False)
        Q = x_Q, int.from_bytes(pub_key[ec.p_size + 1:],
                                byteorder="big",
                                signed=False)
        if Q[1] == 0:  # infinity point in affine coordinates
            raise BTClibValueError(
                "no bytes representation for infinity point")
        if ec.is_on_curve(Q):
            return Q
        raise BTClibValueError(f"point not on curve: {Q}")
    else:
        raise BTClibValueError(f"not a point: {pub_key!r}")