Esempio n. 1
0
    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)
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
def bn_is_normalized(check_bn, modulus):
    """
    Returns ``True`` if ``check_bn`` is in ``[0, modulus)``, ``False`` otherwise.
    """
    zero = backend._int_to_bn(0)
    zero = BACKEND_FFI.gc(zero, BACKEND_LIB.BN_clear_free)

    check_sign = BACKEND_LIB.BN_cmp(check_bn, zero)
    range_check = BACKEND_LIB.BN_cmp(check_bn, modulus)
    return check_sign in (0, 1) and range_check == -1
Esempio n. 5
0
def _bn_is_on_curve(check_bn, curve_nid: int):
    """
    Checks if a given OpenSSL BIGNUM is within the provided curve's order.
    Returns True if the provided BN is on the curve, or False if the BN is zero
    or not on the curve.
    """
    ec_order = _get_ec_order_by_curve_nid(curve_nid)

    check_sign = backend._lib.BN_cmp(check_bn, backend._int_to_bn(0))
    range_check = backend._lib.BN_cmp(check_bn, ec_order)
    return check_sign == 1 and range_check == -1
Esempio n. 6
0
    def __eq__(self, other):
        """
        Compares the two BIGNUMS or int.
        """
        if type(other) == int:
            other = backend._int_to_bn(other)
            other = backend._ffi.gc(other, backend._lib.BN_clear_free)

            other = BigNum(other, None, None, None)

        # -1 less than, 0 is equal to, 1 is greater than
        return not bool(backend._lib.BN_cmp(self.bignum, other.bignum))
Esempio n. 7
0
def _bn_is_on_curve(check_bn, curve: 'Curve'):
    """
    Checks if a given OpenSSL BIGNUM is within the provided curve's order.
    Returns True if the provided BN is on the curve, or False if the BN is zero
    or not on the curve.
    """
    zero = backend._int_to_bn(0)
    zero = backend._ffi.gc(zero, backend._lib.BN_clear_free)

    check_sign = backend._lib.BN_cmp(check_bn, zero)
    range_check = backend._lib.BN_cmp(check_bn, curve.order)
    return check_sign == 1 and range_check == -1
Esempio n. 8
0
    def __neg__(self) -> 'CurveBN':
        """
        Computes the modular opposite (i.e., additive inverse) of a BIGNUM

        """
        zero = backend._int_to_bn(0)
        zero = backend._ffi.gc(zero, backend._lib.BN_clear_free)

        the_opposite = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_sub(the_opposite, zero, self.bignum,
                                          self.curve.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(the_opposite, self.curve)
Esempio n. 9
0
def bn_from_int(py_int: int, check_modulus=None):
    """
    Converts the given Python int to an OpenSSL BIGNUM. If ``modulus`` is
    provided, it will check if the Python integer is within ``[0, modulus)``.
    """
    conv_bn = backend._int_to_bn(py_int)
    conv_bn = BACKEND_FFI.gc(conv_bn, BACKEND_LIB.BN_clear_free)

    if check_modulus and not bn_is_normalized(conv_bn, check_modulus):
        raise ValueError(
            f"The Python integer given ({py_int}) is not under the provided modulus."
        )

    BACKEND_LIB.BN_set_flags(conv_bn, BACKEND_LIB.BN_FLG_CONSTTIME)
    return conv_bn
Esempio n. 10
0
    def __mod__(self, other):
        """
        Performs a BN_nnmod on two BIGNUMS.
        """
        if type(other) == int:
            other = backend._int_to_bn(other)
            other = backend._ffi.gc(other, backend._lib.BN_clear_free)

            other = BigNum(other, None, None, None)

        rem = backend._lib.BN_new()
        backend.openssl_assert(rem != backend._ffi.NULL)
        rem = backend._ffi.gc(rem, backend._lib.BN_clear_free)

        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_nnmod(rem, self.bignum, other.bignum, bn_ctx)
            backend.openssl_assert(res == 1)

        return BigNum(rem, self.curve_nid, self.group, self.order)
Esempio n. 11
0
def _int_to_bn(py_int: int, curve: 'Curve'=None, set_consttime_flag=True):
    """
    Converts the given Python int to an OpenSSL BIGNUM. If a curve is
    provided, it will check if the Python integer is within the order of that
    curve. If it's not within the order, it will raise a ValueError.

    If set_consttime_flag is set to True, OpenSSL will use constant time
    operations when using this CurveBN.
    """
    conv_bn = backend._int_to_bn(py_int)
    conv_bn = backend._ffi.gc(conv_bn, backend._lib.BN_clear_free)
    
    if curve:
        on_curve = _bn_is_on_curve(conv_bn, curve)
        if not on_curve:
            raise ValueError("The Python integer given is not on the provided curve.")

    if set_consttime_flag:
        backend._lib.BN_set_flags(conv_bn, backend._lib.BN_FLG_CONSTTIME)
    return conv_bn