def __eq__(self, other): self_curve_nid = backend._elliptic_curve_to_nid(self.curve) other_curve_nid = backend._elliptic_curve_to_nid(other.curve) # TODO: This is not comparing the order, which currently is an OpenSSL pointer self_attributes = self_curve_nid, self.g, self.CURVE_KEY_SIZE_BYTES, self.u others_attributes = other_curve_nid, other.g, other.CURVE_KEY_SIZE_BYTES, other.u return self_attributes == others_attributes
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 = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) generator = backend._lib.EC_GROUP_get0_generator(group) backend.openssl_assert(generator != backend._ffi.NULL) rand_point = backend._lib.EC_POINT_new(group) backend.openssl_assert(rand_point != backend._ffi.NULL) rand_point = backend._ffi.gc(rand_point, backend._lib.EC_POINT_clear_free) rand_bn = BigNum.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_affine(cls, coords, curve: ec.EllipticCurve = None): """ Returns a Point object from the given affine coordinates in a tuple in the format of (x, y) and a given curve. """ 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 affine_x, affine_y = coords if type(affine_x) == int: affine_x = openssl._int_to_bn(affine_x) if type(affine_y) == int: affine_y = openssl._int_to_bn(affine_y) group = openssl._get_ec_group_by_curve_nid(curve_nid) ec_point = openssl._get_EC_POINT_via_affine(affine_x, affine_y, ec_group=group) return cls(ec_point, curve_nid, group)
def gen_rand(cls, curve: ec.EllipticCurve = None): """ Returns a BigNum object with a cryptographically secure BigNum based on the given curve. """ curve = curve if curve is not None else default_curve() curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) order_int = backend._bn_to_int(order) # Generate random number on curve key_size = get_curve_keysize_bytes(curve) rand_num = int.from_bytes(os.urandom(key_size), 'big') while rand_num >= order_int or rand_num <= 0: rand_num = int.from_bytes(os.urandom(key_size), 'big') new_rand_bn = backend._int_to_bn(rand_num) new_rand_bn = backend._ffi.gc(new_rand_bn, backend._lib.BN_free) return cls(new_rand_bn, curve_nid, group, order)
def gen_rand(cls, curve: ec.EllipticCurve = None): """ Returns a BigNum object with a cryptographically secure BigNum based on the given curve. """ curve = curve if curve is not None else default_curve() curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_clear_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) new_rand_bn = backend._lib.BN_new() backend.openssl_assert(new_rand_bn != backend._ffi.NULL) new_rand_bn = backend._ffi.gc(new_rand_bn, backend._lib.BN_clear_free) rand_res = backend._lib.BN_rand_range(new_rand_bn, order) backend.openssl_assert(rand_res == 1) return cls(new_rand_bn, curve_nid, group, order)
def from_int(cls, num, curve: ec.EllipticCurve = None): """ Returns a BigNum object from a given integer on a curve. """ 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 group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_clear_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) order_int = backend._bn_to_int(order) if num <= 0 or num >= order_int: # TODO: Handle this better maybe? Ask David. raise ValueError("Integer provided is not on the given curve.") bignum = backend._int_to_bn(num) bignum = backend._ffi.gc(bignum, backend._lib.BN_clear_free) return cls(bignum, curve_nid, group, order)
def from_affine(cls, coords, curve: ec.EllipticCurve = None): """ Returns a Point object from the given affine coordinates in a tuple in the format of (x, y) and a given curve. """ 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 affine_x, affine_y = coords if type(affine_x) == int: affine_x = backend._int_to_bn(affine_x) affine_x = backend._ffi.gc(affine_x, backend._lib.BN_clear_free) if type(affine_y) == int: affine_y = backend._int_to_bn(affine_y) affine_y = backend._ffi.gc(affine_y, backend._lib.BN_clear_free) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) ec_point = backend._lib.EC_POINT_new(group) backend.openssl_assert(ec_point != backend._ffi.NULL) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_POINT_set_affine_coordinates_GFp( group, ec_point, affine_x, affine_y, bn_ctx) backend.openssl_assert(res == 1) return Point(ec_point, curve_nid, group)
def get_order_from_curve(cls, curve: ec.EllipticCurve=None): """ Returns the order from the given curve as a CurveBN. """ 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 group = openssl._get_ec_group_by_curve_nid(curve_nid) order = openssl._get_ec_order_by_curve_nid(curve_nid) return CurveBN(order, curve_nid, group, order)
def get_generator_from_curve(cls, curve: ec.EllipticCurve=None): """ Returns the generator Point from the given curve as a Point object. """ 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 group = openssl._get_ec_group_by_curve_nid(curve_nid) generator = openssl._get_ec_generator_by_curve_nid(curve_nid) return cls(generator, curve_nid, group)
def __init__(self, curve: ec.EllipticCurve): from umbral.point import Point, unsafe_hash_to_point from umbral.utils import get_curve_keysize_bytes self.curve = curve curve_nid = backend._elliptic_curve_to_nid(curve) self.g = Point.get_generator_from_curve(self.curve) self.order = openssl._get_ec_order_by_curve_nid(curve_nid) g_bytes = self.g.to_bytes(is_compressed=True) self.CURVE_KEY_SIZE_BYTES = get_curve_keysize_bytes(self.curve) parameters_seed = b'NuCypherKMS/UmbralParameters/' self.u = unsafe_hash_to_point(g_bytes, self, parameters_seed + b'u')
def get_generator_from_curve(cls, curve: ec.EllipticCurve = None): """ Returns the generator Point from the given curve as a Point object. """ 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 group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) generator = backend._lib.EC_GROUP_get0_generator(group) backend.openssl_assert(generator != backend._ffi.NULL) return cls(generator, curve_nid, group)
def hash(cls, *crypto_items, params=None): params = params if params is not None else default_params() curve_nid = backend._elliptic_curve_to_nid(params.curve) order = openssl._get_ec_order_by_curve_nid(curve_nid) group = openssl._get_ec_group_by_curve_nid(curve_nid) # TODO: Clean this in an upcoming cleanup of pyUmbral blake2b = hashes.Hash(hashes.BLAKE2b(64), backend=backend) for item in crypto_items: try: item_bytes = item.to_bytes() except AttributeError: if isinstance(item, bytes): item_bytes = item else: raise TypeError( "{} is not acceptable type, received {}".format( item, type(item))) blake2b.update(item_bytes) hash_digest = blake2b.finalize() hash_digest = int.from_bytes(hash_digest, byteorder='big', signed=False) hash_digest = openssl._int_to_bn(hash_digest) _1 = backend._lib.BN_value_one() order_minus_1 = openssl._get_new_BN() res = backend._lib.BN_sub(order_minus_1, order, _1) backend.openssl_assert(res == 1) bignum = openssl._get_new_BN() with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.BN_mod(bignum, hash_digest, order_minus_1, bn_ctx) backend.openssl_assert(res == 1) res = backend._lib.BN_add(bignum, bignum, _1) backend.openssl_assert(res == 1) return cls(bignum, curve_nid, group, order)
def from_int(cls, num, curve: ec.EllipticCurve = None): """ Returns a CurveBN object from a given integer on a curve. By default, the underlying OpenSSL BIGNUM has BN_FLG_CONSTTIME set for constant time operations. """ 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 group = openssl._get_ec_group_by_curve_nid(curve_nid) order = openssl._get_ec_order_by_curve_nid(curve_nid) conv_bn = openssl._int_to_bn(num, curve_nid) return cls(conv_bn, curve_nid, group, order)
def CURVE_GET_ORDER(curve) -> _EllipticCurvePrivateKey: """ Returns the order of the curve provided. This returns it as a private key to use in the above operations, if needed. """ curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) return _bignum_to_private_key(backend, group, order)
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 # Check if compressed if data[0] in [2, 3]: type_y = data[0] - 2 if len(data[1:]) > get_curve_keysize_bytes(curve): raise ValueError("X coordinate too large for curve.") affine_x = BigNum.from_bytes(data[1:], curve) ec_point = backend._lib.EC_POINT_new(affine_x.group) backend.openssl_assert(ec_point != backend._ffi.NULL) ec_point = backend._ffi.gc(ec_point, backend._lib.EC_POINT_clear_free) 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: key_size = get_curve_keysize_bytes(curve) affine_x = int.from_bytes(data[1:key_size + 1], 'big') affine_y = int.from_bytes(data[1 + key_size:], 'big') return Point.from_affine((affine_x, affine_y), curve) else: raise ValueError("Invalid point serialization.")
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 CURVE_GET_GENERATOR(curve) -> _EllipticCurvePublicKey: """ Returns the generator point of the curve provided. This returns it as a public key to use in the above operations, if needed. """ curve_nid = backend._elliptic_curve_to_nid(curve) group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) gen_point = backend._lib.EC_POINT_new(group) backend.openssl_assert(gen_point != backend._ffi.NULL) gen_point = backend._ffi.gc(gen_point, backend._lib.EC_POINT_free) generator = backend._lib.EC_GROUP_get0_generator(group) backend.openssl_assert(generator != backend._ffi.NULL) res = backend._lib.EC_POINT_copy(gen_point, generator) backend.openssl_assert(res == 1) return _point_to_public_key(backend, group, generator)
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 gen_rand(cls, curve: ec.EllipticCurve = None): """ Returns a CurveBN object with a cryptographically secure OpenSSL BIGNUM based on the given curve. By default, the underlying OpenSSL BIGNUM has BN_FLG_CONSTTIME set for constant time operations. """ 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) order = openssl._get_ec_order_by_curve_nid(curve_nid) new_rand_bn = openssl._get_new_BN() rand_res = backend._lib.BN_rand_range(new_rand_bn, order) backend.openssl_assert(rand_res == 1) if not openssl._bn_is_on_curve(new_rand_bn, curve_nid): new_rand_bn = cls.gen_rand(curve=curve) return new_rand_bn return cls(new_rand_bn, curve_nid, group, order)
def get_order_from_curve(cls, curve: ec.EllipticCurve = None): """ Returns the order from the given curve as a BigNum. """ 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 group = backend._lib.EC_GROUP_new_by_curve_name(curve_nid) backend.openssl_assert(group != backend._ffi.NULL) order = backend._lib.BN_new() backend.openssl_assert(order != backend._ffi.NULL) order = backend._ffi.gc(order, backend._lib.BN_clear_free) with backend._tmp_bn_ctx() as bn_ctx: res = backend._lib.EC_GROUP_get_order(group, order, bn_ctx) backend.openssl_assert(res == 1) return BigNum(order, curve_nid, group, order)