def _ecc_decode_compressed_point()

in src/aws_encryption_sdk/internal/crypto/elliptic_curve.py [0:0]


def _ecc_decode_compressed_point(curve, compressed_point):
    """Decodes a compressed elliptic curve point
        as described in SEC-1 v2 section 2.3.4
        http://www.secg.org/sec1-v2.pdf

    :param curve: Elliptic curve type to generate
    :type curve: cryptography.hazmat.primitives.asymmetric.ec.EllipticCurve
    :param bytes compressed_point: Encoded compressed elliptic curve point
    :returns: X and Y coordinates from compressed point
    :rtype: tuple of longs
    :raises NotSupportedError: for non-prime curves, unsupported prime curves, and points at infinity
    """
    if not compressed_point:
        raise NotSupportedError("Points at infinity are not allowed")
    y_order_map = {b"\x02": 0, b"\x03": 1}
    raw_x = compressed_point[1:]
    raw_x = to_bytes(raw_x)
    x = int.from_bytes(raw_x, "big")
    raw_y = compressed_point[0]
    # In Python3, bytes index calls return int values rather than strings
    if isinstance(raw_y, six.integer_types):
        raw_y = six.b(chr(raw_y))
    elif isinstance(raw_y, six.string_types):
        raw_y = six.b(raw_y)
    y_order = y_order_map[raw_y]
    # If curve in prime field.
    if curve.name.startswith("secp"):
        try:
            params = _ECC_CURVE_PARAMETERS[curve.name]
        except KeyError:
            raise NotSupportedError("Curve {name} is not supported at this time".format(name=curve.name))
        alpha = (pow(x, 3, params.p) + (params.a * x % params.p) + params.b) % params.p
        # Only works for p % 4 == 3 at this time.
        # This is the case for all currently supported algorithms.
        # This will need to be expanded if curves which do not match this are added.
        #  Python-ecdsa has these algorithms implemented.  Copy or reference?
        #  https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm
        #  Handbook of Applied Cryptography, algorithms 3.34 - 3.39
        if params.p % 4 == 3:
            beta = pow(alpha, (params.p + 1) // 4, params.p)
        else:
            raise NotSupportedError("S not 1 :: Curve not supported at this time")
        if beta % 2 == y_order:
            y = beta
        else:
            y = params.p - beta
    else:
        raise NotSupportedError("Non-prime curves are not supported at this time")
    return x, y