Exemplo n.º 1
0
    def hash(cls, *crypto_items, params: UmbralParameters) -> 'CurveBN':
        # 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 = openssl._bytes_to_bn(blake2b.finalize())

        _1 = backend._lib.BN_value_one()

        order_minus_1 = openssl._get_new_BN()
        res = backend._lib.BN_sub(order_minus_1, params.curve.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, params.curve)
Exemplo n.º 2
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)
Exemplo n.º 3
0
    def __add__(self, other) -> 'CurveBN':
        """
        Performs a BN_mod_add on two BIGNUMs.
        """
        op_sum = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            res = backend._lib.BN_mod_add(op_sum, self.bignum, other.bignum,
                                          self.curve.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(op_sum, self.curve)
Exemplo n.º 4
0
    def __sub__(self, other):
        """
        Performs a BN_mod_sub on two BIGNUMS.
        """
        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.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(diff, self.curve_nid, self.group, self.order)
Exemplo n.º 5
0
    def __mul__(self, other) -> 'CurveBN':
        """
        Performs a BN_mod_mul between two BIGNUMS.
        """
        if type(other) != CurveBN:
            return NotImplemented

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

        return CurveBN(product, self.curve)
Exemplo n.º 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)
Exemplo n.º 7
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)
Exemplo n.º 8
0
def hash_to_curvebn(*crypto_items,
                    params: UmbralParameters,
                    customization_string: bytes = b'',
                    hash_class: Type[Hash] = Blake2b) -> CurveBN:

    customization_string = b'hash_to_curvebn' + customization_string
    hash_function = hash_class(customization_string=customization_string)

    for item in crypto_items:
        try:
            item_bytes = item.to_bytes()
        except AttributeError:
            if isinstance(item, bytes):
                item_bytes = item
            else:
                raise TypeError("Input with type {} not accepted".format(
                    type(item)))
        hash_function.update(item_bytes)

    hash_digest = openssl._bytes_to_bn(hash_function.finalize())

    one = backend._lib.BN_value_one()

    order_minus_1 = openssl._get_new_BN()
    res = backend._lib.BN_sub(order_minus_1, params.curve.order, one)
    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, one)
    backend.openssl_assert(res == 1)

    return CurveBN(bignum, params.curve)
Exemplo n.º 9
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)
Exemplo n.º 10
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)
Exemplo n.º 11
0
    def gen_rand(cls, curve: Optional[Curve] = None) -> 'CurveBN':
        """
        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()

        new_rand_bn = openssl._get_new_BN()
        rand_res = backend._lib.BN_rand_range(new_rand_bn, curve.order)
        backend.openssl_assert(rand_res == 1)

        if not openssl._bn_is_on_curve(new_rand_bn, curve):
            new_rand_bn = cls.gen_rand(curve=curve)
            return new_rand_bn

        return cls(new_rand_bn, curve)
Exemplo n.º 12
0
    def __truediv__(self, other):
        """
        Performs a BN_div on two BIGNUMs (modulo the order of the curve).

        WARNING: Only in constant time if BN_FLG_CONSTTIME is set on the BN.
        """
        product = openssl._get_new_BN()
        with backend._tmp_bn_ctx() as bn_ctx:
            inv_other = backend._lib.BN_mod_inverse(backend._ffi.NULL,
                                                    other.bignum, self.order,
                                                    bn_ctx)
            backend.openssl_assert(inv_other != backend._ffi.NULL)

            res = backend._lib.BN_mod_mul(product, self.bignum, inv_other,
                                          self.order, bn_ctx)
            backend.openssl_assert(res == 1)

        return CurveBN(product, self.curve_nid, self.group, self.order)
Exemplo n.º 13
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)
Exemplo n.º 14
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)
Exemplo n.º 15
0
    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)