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