Exemple #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 = 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)
Exemple #2
0
 def from_int(cls, num: int, curve: Optional[Curve] = None) -> 'CurveBN':
     """
     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()
     conv_bn = openssl._int_to_bn(num, curve)
     return cls(conv_bn, curve)
Exemple #3
0
    def from_affine(cls,
                    coords: Tuple[int, int],
                    curve: Optional[Curve] = None) -> 'Point':
        """
        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()

        affine_x, affine_y = coords
        if type(affine_x) == int:
            affine_x = openssl._int_to_bn(affine_x, curve=curve)

        if type(affine_y) == int:
            affine_y = openssl._int_to_bn(affine_y, curve=curve)

        ec_point = openssl._get_EC_POINT_via_affine(affine_x, affine_y, curve)
        return cls(ec_point, curve)
Exemple #4
0
    def __eq__(self, other):
        """
        Compares the two BIGNUMS or int.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(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))
Exemple #5
0
    def __eq__(self, other) -> bool:
        """
        Compares the two BIGNUMS or int.
        """
        # TODO: Should this stay in or not?
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, self.curve)

        # -1 less than, 0 is equal to, 1 is greater than
        return not bool(backend._lib.BN_cmp(self.bignum, other.bignum))
Exemple #6
0
    def __mod__(self, other):
        """
        Performs a BN_nnmod on two BIGNUMS.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, None, None, None)

        rem = openssl._get_new_BN()
        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 CurveBN(rem, self.curve_nid, self.group, self.order)
Exemple #7
0
    def __sub__(self, other: Union[int, 'CurveBN']) -> 'CurveBN':
        """
        Performs a BN_mod_sub on two BIGNUMS.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, self.curve)

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

        return CurveBN(diff, self.curve)
Exemple #8
0
    def __mod__(self, other: Union[int, 'CurveBN']) -> 'CurveBN':
        """
        Performs a BN_nnmod on two BIGNUMS.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, self.curve)

        other = cast('CurveBN', other)  # This is just for mypy

        rem = openssl._get_new_BN()
        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 CurveBN(rem, self.curve)
Exemple #9
0
    def __pow__(self, other):
        """
        Performs a BN_mod_exp on two BIGNUMS.

        WARNING: Only in constant time if BN_FLG_CONSTTIME is set on the BN.
        """
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, None, None, None)

        power = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx, openssl._tmp_bn_mont_ctx(self.order) as bn_mont_ctx:
            res = backend._lib.BN_mod_exp_mont(
                power, self.bignum, other.bignum, self.order, bn_ctx, bn_mont_ctx
            )
            backend.openssl_assert(res == 1)

        return CurveBN(power, self.curve_nid, self.group, self.order)
Exemple #10
0
    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)
Exemple #11
0
    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)
Exemple #12
0
    def __pow__(self, other : Union[int, 'CurveBN']) -> 'CurveBN':
        """
        Performs a BN_mod_exp on two BIGNUMS.

        WARNING: Only in constant time if BN_FLG_CONSTTIME is set on the BN.
        """
        # TODO: Should this stay in or not?
        if type(other) == int:
            other = openssl._int_to_bn(other)
            other = CurveBN(other, self.curve)

        power = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx, openssl._tmp_bn_mont_ctx(self.curve.order) as bn_mont_ctx:
            res = backend._lib.BN_mod_exp_mont(
                power, self.bignum, other.bignum, self.curve.order, bn_ctx, bn_mont_ctx
            )
            backend.openssl_assert(res == 1)

        return CurveBN(power, self.curve)
Exemple #13
0
    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.")