def to_cryptography_privkey(self): """ Returns a cryptography.io EllipticCurvePrivateKey from the Umbral key. """ backend = default_backend() backend.openssl_assert(self.bn_key.group != backend._ffi.NULL) backend.openssl_assert(self.bn_key.bignum != backend._ffi.NULL) ec_key = backend._lib.EC_KEY_new() backend.openssl_assert(ec_key != backend._ffi.NULL) ec_key = backend._ffi.gc(ec_key, backend._lib.EC_KEY_free) set_group_result = backend._lib.EC_KEY_set_group( ec_key, self.bn_key.group) backend.openssl_assert(set_group_result == 1) set_privkey_result = backend._lib.EC_KEY_set_private_key( ec_key, self.bn_key.bignum) backend.openssl_assert(set_privkey_result == 1) # Get public key point = openssl._get_new_EC_POINT(ec_group=self.bn_key.group) with backend._tmp_bn_ctx() as bn_ctx: mult_result = backend._lib.EC_POINT_mul(self.bn_key.group, point, self.bn_key.bignum, backend._ffi.NULL, backend._ffi.NULL, bn_ctx) backend.openssl_assert(mult_result == 1) set_pubkey_result = backend._lib.EC_KEY_set_public_key(ec_key, point) backend.openssl_assert(set_pubkey_result == 1) evp_pkey = backend._ec_cdata_to_evp_pkey(ec_key) return _EllipticCurvePrivateKey(backend, ec_key, evp_pkey)
def __add__(self, other): """ Performs an EC_POINT_add on two EC_POINTS. """ op_sum = openssl._get_new_EC_POINT(ec_group=self.group) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_add(self.group, op_sum, self.ec_point, other.ec_point, bn_ctx) backend.openssl_assert(res == 1) return Point(op_sum, self.curve_nid, self.group)
def __mul__(self, other): """ Performs an EC_POINT_mul on an EC_POINT and a BIGNUM. """ prod = openssl._get_new_EC_POINT(ec_group=self.group) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_mul( self.group, prod, backend._ffi.NULL, self.ec_point, other.bignum, bn_ctx ) backend.openssl_assert(res == 1) return Point(prod, self.curve_nid, self.group)
def __mul__(self, other) -> 'Point': """ Performs an EC_POINT_mul on an EC_POINT and a BIGNUM. """ # TODO: Check that both points use the same curve. prod = openssl._get_new_EC_POINT(self.curve) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_mul(self.curve.ec_group, prod, backend._ffi.NULL, self.ec_point, other.bignum, bn_ctx) backend.openssl_assert(res == 1) return Point(prod, self.curve)
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'Point': """ Returns a Point object from the given byte data on the curve provided. """ curve = curve if curve is not None else default_curve() point = openssl._get_new_EC_POINT(curve) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_oct2point(curve.ec_group, point, data, len(data), bn_ctx) backend.openssl_assert(res == 1) return cls(point, curve)
def gen_rand(cls, curve: Optional[Curve] = None) -> 'Point': """ Returns a Point object with a cryptographically secure EC_POINT based on the provided curve. """ curve = curve if curve is not None else default_curve() rand_point = openssl._get_new_EC_POINT(curve) rand_bn = CurveBN.gen_rand(curve).bignum with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_mul(curve.ec_group, rand_point, backend._ffi.NULL, curve.generator, rand_bn, bn_ctx) backend.openssl_assert(res == 1) return cls(rand_point, curve)
def gen_rand(cls, curve: ec.EllipticCurve=None): """ Returns a Point object with a cryptographically secure EC_POINT based on the provided curve. """ curve = curve if curve is not None else default_curve() curve_nid = backend._elliptic_curve_to_nid(curve) group = openssl._get_ec_group_by_curve_nid(curve_nid) generator = openssl._get_ec_generator_by_curve_nid(curve_nid) rand_point = openssl._get_new_EC_POINT(ec_group=group) rand_bn = CurveBN.gen_rand(curve).bignum with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_mul( group, rand_point, backend._ffi.NULL, generator, rand_bn, bn_ctx ) backend.openssl_assert(res == 1) return Point(rand_point, curve_nid, group)
def from_bytes(cls, data, curve: ec.EllipticCurve = None): """ Returns a Point object from the given byte data on the curve provided. """ curve = curve if curve is not None else default_curve() try: curve_nid = backend._elliptic_curve_to_nid(curve) except AttributeError: # Presume that the user passed in the curve_nid curve_nid = curve compressed_size = cls.expected_bytes_length(curve) # Check if compressed if data[0] in [2, 3]: if len(data) != compressed_size: raise ValueError("X coordinate too large for curve.") affine_x = CurveBN.from_bytes(data[1:], curve) type_y = data[0] - 2 ec_point = openssl._get_new_EC_POINT(ec_group=affine_x.group) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_set_compressed_coordinates_GFp( affine_x.group, ec_point, affine_x.bignum, type_y, bn_ctx) backend.openssl_assert(res == 1) return cls(ec_point, curve_nid, affine_x.group) # Handle uncompressed point elif data[0] == 4: coord_size = compressed_size - 1 uncompressed_size = 1 + 2 * coord_size if len(data) != uncompressed_size: raise ValueError( "uncompressed point does not have right size.") affine_x = int.from_bytes(data[1:coord_size + 1], 'big') affine_y = int.from_bytes(data[1 + coord_size:], 'big') return cls.from_affine((affine_x, affine_y), curve) else: raise ValueError("Invalid point serialization.")
def from_bytes(cls, data: bytes, curve: Optional[Curve] = None) -> 'Point': """ Returns a Point object from the given byte data on the curve provided. """ curve = curve if curve is not None else default_curve() compressed_size = cls.expected_bytes_length(curve) # Check if compressed if data[0] in [2, 3]: if len(data) != compressed_size: raise ValueError("X coordinate too large for curve.") affine_x = int.from_bytes(data[1:], 'big') affine_x = openssl._int_to_bn(affine_x, curve=None) type_y = data[0] - 2 ec_point = openssl._get_new_EC_POINT(curve) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_set_compressed_coordinates_GFp( curve.ec_group, ec_point, affine_x, type_y, bn_ctx) backend.openssl_assert(res == 1) return cls(ec_point, curve) # Handle uncompressed point # TODO: Give better error messages elif data[0] == 4: coord_size = compressed_size - 1 uncompressed_size = 1 + (2 * coord_size) if len(data) != uncompressed_size: raise ValueError( "Uncompressed point does not have right size.") affine_x = int.from_bytes(data[1:coord_size + 1], 'big') affine_y = int.from_bytes(data[1 + coord_size:], 'big') return cls.from_affine((affine_x, affine_y), curve) else: raise ValueError("Invalid point serialization.")