Ejemplo n.º 1
0
 def randint(self, a, b):
     """Return a random integer N such that a <= N <= b."""
     if not is_native_int(a) or not is_native_int(b):
         raise TypeError("randint requires integer arguments")
     N = self.randrange(a, b + 1)
     assert a <= N <= b
     return N
Ejemplo n.º 2
0
    def randrange(self, *args):
        """randrange([start,] stop[, step]):
        Return a randomly-selected element from range(start, stop, step)."""
        if len(args) == 3:
            (start, stop, step) = args
        elif len(args) == 2:
            (start, stop) = args
            step = 1
        elif len(args) == 1:
            (stop, ) = args
            start = 0
            step = 1
        else:
            raise TypeError("randrange expected at most 3 arguments, got %d" %
                            (len(args), ))
        if (not is_native_int(start) or not is_native_int(stop)
                or not is_native_int(step)):
            raise TypeError("randrange requires integer arguments")
        if step == 0:
            raise ValueError("randrange step argument must not be zero")

        num_choices = ceil_div(stop - start, step)
        if num_choices < 0:
            num_choices = 0
        if num_choices < 1:
            raise ValueError("empty range for randrange(%r, %r, %r)" %
                             (start, stop, step))

        # Pick a random number in the range of possible numbers
        r = num_choices
        while r >= num_choices:
            r = self.getrandbits(size(num_choices))

        return start + (step * r)
Ejemplo n.º 3
0
    def randrange(self, *args):
        """randrange([start,] stop[, step]):
        Return a randomly-selected element from range(start, stop, step)."""
        if len(args) == 3:
            (start, stop, step) = args
        elif len(args) == 2:
            (start, stop) = args
            step = 1
        elif len(args) == 1:
            (stop,) = args
            start = 0
            step = 1
        else:
            raise TypeError("randrange expected at most 3 arguments, got %d" % (len(args),))
        if (not is_native_int(start) or not is_native_int(stop) or not
                is_native_int(step)):
            raise TypeError("randrange requires integer arguments")
        if step == 0:
            raise ValueError("randrange step argument must not be zero")

        num_choices = ceil_div(stop - start, step)
        if num_choices < 0:
            num_choices = 0
        if num_choices < 1:
            raise ValueError("empty range for randrange(%r, %r, %r)" % (start, stop, step))

        # Pick a random number in the range of possible numbers
        r = num_choices
        while r >= num_choices:
            r = self.getrandbits(size(num_choices))

        return start + (step * r)
Ejemplo n.º 4
0
 def randint(self, a, b):
     """Return a random integer N such that a <= N <= b."""
     if not is_native_int(a) or not is_native_int(b):
         raise TypeError("randint requires integer arguments")
     N = self.randrange(a, b+1)
     assert a <= N <= b
     return N
Ejemplo n.º 5
0
    def inplace_pow(self, exponent, modulus=None):

        if modulus is None:
            if exponent < 0:
                raise ValueError("Exponent must not be negative")

            # Normal exponentiation
            if exponent > 256:
                raise ValueError("Exponent is too big")
            _gmp.mpz_pow_ui(
                self._mpz_p,
                self._mpz_p,  # Base
                c_ulong(int(exponent)))
        else:
            # Modular exponentiation
            if not isinstance(modulus, IntegerGMP):
                modulus = IntegerGMP(modulus)
            if not modulus:
                raise ZeroDivisionError("Division by zero")
            if modulus.is_negative():
                raise ValueError("Modulus must be positive")
            if is_native_int(exponent):
                if exponent < 0:
                    raise ValueError("Exponent must not be negative")
                if exponent < 65536:
                    _gmp.mpz_powm_ui(self._mpz_p, self._mpz_p,
                                     c_ulong(exponent), modulus._mpz_p)
                    return self
                exponent = IntegerGMP(exponent)
            elif exponent.is_negative():
                raise ValueError("Exponent must not be negative")
            _gmp.mpz_powm(self._mpz_p, self._mpz_p, exponent._mpz_p,
                          modulus._mpz_p)
        return self
Ejemplo n.º 6
0
 def __isub__(self, term):
     if is_native_int(term):
         if 0 <= term < 65536:
             _gmp.mpz_sub_ui(self._mpz_p, self._mpz_p, c_ulong(term))
             return self
         if -65535 < term < 0:
             _gmp.mpz_add_ui(self._mpz_p, self._mpz_p, c_ulong(-term))
             return self
         term = IntegerGMP(term)
     _gmp.mpz_sub(self._mpz_p, self._mpz_p, term._mpz_p)
     return self
Ejemplo n.º 7
0
    def fail_if_divisible_by(self, small_prime):
        """Raise an exception if the small prime is a divisor."""

        if is_native_int(small_prime):
            if 0 < small_prime < 65536:
                if _gmp.mpz_divisible_ui_p(self._mpz_p, c_ulong(small_prime)):
                    raise ValueError("The value is composite")
                return
            small_prime = IntegerGMP(small_prime)
        if _gmp.mpz_divisible_p(self._mpz_p, small_prime._mpz_p):
            raise ValueError("The value is composite")
Ejemplo n.º 8
0
    def gcd(self, term):
        """Compute the greatest common denominator between this
        number and another term."""

        result = IntegerGMP(0)
        if is_native_int(term):
            if 0 < term < 65535:
                _gmp.mpz_gcd_ui(result._mpz_p, self._mpz_p, c_ulong(term))
                return result
            term = IntegerGMP(term)
        _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p)
        return result
Ejemplo n.º 9
0
 def __imul__(self, term):
     if is_native_int(term):
         if 0 <= term < 65536:
             _gmp.mpz_mul_ui(self._mpz_p, self._mpz_p, c_ulong(term))
             return self
         if -65535 < term < 0:
             _gmp.mpz_mul_ui(self._mpz_p, self._mpz_p, c_ulong(-term))
             _gmp.mpz_neg(self._mpz_p, self._mpz_p)
             return self
         term = IntegerGMP(term)
     _gmp.mpz_mul(self._mpz_p, self._mpz_p, term._mpz_p)
     return self
Ejemplo n.º 10
0
    def fail_if_divisible_by(self, small_prime):
        """Raise an exception if the small prime is a divisor."""

        if is_native_int(small_prime):
            if 0 < small_prime < 65536:
                if _gmp.mpz_divisible_ui_p(self._mpz_p,
                                           c_ulong(small_prime)):
                    raise ValueError("The value is composite")
                return
            small_prime = IntegerGMP(small_prime)
        if _gmp.mpz_divisible_p(self._mpz_p,
                                small_prime._mpz_p):
            raise ValueError("The value is composite")
Ejemplo n.º 11
0
    def gcd(self, term):
        """Compute the greatest common denominator between this
        number and another term."""

        result = IntegerGMP(0)
        if is_native_int(term):
            if 0 < term < 65535:
                _gmp.mpz_gcd_ui(result._mpz_p,
                                self._mpz_p,
                                c_ulong(term))
                return result
            term = IntegerGMP(term)
        _gmp.mpz_gcd(result._mpz_p, self._mpz_p, term._mpz_p)
        return result
Ejemplo n.º 12
0
    def __init__(self, encoded_value):
        """Initialize the element to a certain value.

        The value passed as parameter is internally encoded as
        a 128-bit integer, where each bit represents a polynomial
        coefficient. The LSB is the constant coefficient.
        """

        if is_native_int(encoded_value):
            self._value = encoded_value
        elif len(encoded_value) == 16:
            self._value = bytes_to_long(encoded_value)
        else:
            raise ValueError("The encoded value must be an integer or a 16 byte string")
Ejemplo n.º 13
0
    def multiply_accumulate(self, a, b):
        """Increment the number by the product of a and b."""

        if not isinstance(a, IntegerGMP):
            a = IntegerGMP(a)
        if is_native_int(b):
            if 0 < b < 65536:
                _gmp.mpz_addmul_ui(self._mpz_p, a._mpz_p, c_ulong(b))
                return self
            if -65535 < b < 0:
                _gmp.mpz_submul_ui(self._mpz_p, a._mpz_p, c_ulong(-b))
                return self
            b = IntegerGMP(b)
        _gmp.mpz_addmul(self._mpz_p, a._mpz_p, b._mpz_p)
        return self
Ejemplo n.º 14
0
 def __isub__(self, term):
     if is_native_int(term):
         if 0 <= term < 65536:
             _gmp.mpz_sub_ui(self._mpz_p,
                             self._mpz_p,
                             c_ulong(term))
             return self
         if -65535 < term < 0:
             _gmp.mpz_add_ui(self._mpz_p,
                             self._mpz_p,
                             c_ulong(-term))
             return self
         term = IntegerGMP(term)
     _gmp.mpz_sub(self._mpz_p,
                  self._mpz_p,
                  term._mpz_p)
     return self
Ejemplo n.º 15
0
    def __init__(self, value):
        """Initialize the integer to the given value."""

        self._mpz_p = new_mpz()
        self._initialized = False

        if isinstance(value, float):
            raise ValueError("A floating point type is not a natural number")

        self._initialized = True
        
        if is_native_int(value):
            _gmp.mpz_init(self._mpz_p)
            result = _gmp.gmp_sscanf(tobytes(str(value)), b"%Zd", self._mpz_p)
            if result != 1:
                raise ValueError("Error converting '%d'" % value)
        else:
            _gmp.mpz_init_set(self._mpz_p, value._mpz_p)
Ejemplo n.º 16
0
 def __imul__(self, term):
     if is_native_int(term):
         if 0 <= term < 65536:
             _gmp.mpz_mul_ui(self._mpz_p,
                             self._mpz_p,
                             c_ulong(term))
             return self
         if -65535 < term < 0:
             _gmp.mpz_mul_ui(self._mpz_p,
                             self._mpz_p,
                             c_ulong(-term))
             _gmp.mpz_neg(self._mpz_p, self._mpz_p)
             return self
         term = IntegerGMP(term)
     _gmp.mpz_mul(self._mpz_p,
                  self._mpz_p,
                  term._mpz_p)
     return self
Ejemplo n.º 17
0
    def __init__(self, value):
        """Initialize the integer to the given value."""

        self._mpz_p = new_mpz()
        self._initialized = False

        if isinstance(value, float):
            raise ValueError("A floating point type is not a natural number")

        self._initialized = True

        if is_native_int(value):
            _gmp.mpz_init(self._mpz_p)
            result = _gmp.gmp_sscanf(tobytes(str(value)), b"%Zd", self._mpz_p)
            if result != 1:
                raise ValueError("Error converting '%d'" % value)
        else:
            _gmp.mpz_init_set(self._mpz_p, value._mpz_p)
Ejemplo n.º 18
0
    def multiply_accumulate(self, a, b):
        """Increment the number by the product of a and b."""

        if not isinstance(a, IntegerGMP):
            a = IntegerGMP(a)
        if is_native_int(b):
            if 0 < b < 65536:
                _gmp.mpz_addmul_ui(self._mpz_p,
                                   a._mpz_p,
                                   c_ulong(b))
                return self
            if -65535 < b < 0:
                _gmp.mpz_submul_ui(self._mpz_p,
                                   a._mpz_p,
                                   c_ulong(-b))
                return self
            b = IntegerGMP(b)
        _gmp.mpz_addmul(self._mpz_p,
                        a._mpz_p,
                        b._mpz_p)
        return self
Ejemplo n.º 19
0
    def __init__(self, value):
        """Initialize the integer to the given value."""

        self._mpz_p = new_mpz()
        self._initialized = False

        if isinstance(value, float):
            raise ValueError("A floating point type is not a natural number")

        if is_native_int(value):
            _gmp.mpz_init(self._mpz_p)
            self._initialized = True
            if value == 0:
                return

            tmp = new_mpz()
            _gmp.mpz_init(tmp)

            try:
                positive = value >= 0
                reduce = abs(value)
                slots = (reduce.bit_length() - 1) // 32 + 1

                while slots > 0:
                    slots = slots - 1
                    _gmp.mpz_set_ui(
                        tmp, c_ulong(0xFFFFFFFF & (reduce >> (slots * 32))))
                    _gmp.mpz_mul_2exp(tmp, tmp, c_ulong(slots * 32))
                    _gmp.mpz_add(self._mpz_p, self._mpz_p, tmp)
            finally:
                _gmp.mpz_clear(tmp)

            if not positive:
                _gmp.mpz_neg(self._mpz_p, self._mpz_p)

        elif isinstance(value, IntegerGMP):
            _gmp.mpz_init_set(self._mpz_p, value._mpz_p)
            self._initialized = True
        else:
            raise NotImplementedError
Ejemplo n.º 20
0
    def inplace_pow(self, exponent, modulus=None):

        if modulus is None:
            if exponent < 0:
                raise ValueError("Exponent must not be negative")

            # Normal exponentiation
            if exponent > 256:
                raise ValueError("Exponent is too big")
            _gmp.mpz_pow_ui(self._mpz_p,
                            self._mpz_p,   # Base
                            c_ulong(int(exponent))
                            )
        else:
            # Modular exponentiation
            if not isinstance(modulus, IntegerGMP):
                modulus = IntegerGMP(modulus)
            if not modulus:
                raise ZeroDivisionError("Division by zero")
            if modulus.is_negative():
                raise ValueError("Modulus must be positive")
            if is_native_int(exponent):
                if exponent < 0:
                    raise ValueError("Exponent must not be negative")
                if exponent < 65536:
                    _gmp.mpz_powm_ui(self._mpz_p,
                                     self._mpz_p,
                                     c_ulong(exponent),
                                     modulus._mpz_p)
                    return self
                exponent = IntegerGMP(exponent)
            elif exponent.is_negative():
                raise ValueError("Exponent must not be negative")
            _gmp.mpz_powm(self._mpz_p,
                          self._mpz_p,
                          exponent._mpz_p,
                          modulus._mpz_p)
        return self
Ejemplo n.º 21
0
 def __ne__(self, term):
     if not (isinstance(term, IntegerGMP) or is_native_int(term)):
         return True
     return self._apply_and_return(_gmp.mpz_cmp, term) != 0
Ejemplo n.º 22
0
 def __ne__(self, term):
     if not (isinstance(term, IntegerGMP) or is_native_int(term)):
         return True
     return self._apply_and_return(_gmp.mpz_cmp, term) != 0
Ejemplo n.º 23
0
def _create_ctr_cipher(factory, **kwargs):
    """Instantiate a cipher object that performs CTR encryption/decryption.

    :Parameters:
      factory : module
        The underlying block cipher, a module from ``Cryptodome.Cipher``.

    :Keywords:
      nonce : bytes/bytearray/memoryview
        The fixed part at the beginning of the counter block - the rest is
        the counter number that gets increased when processing the next block.
        The nonce must be such that no two messages are encrypted under the
        same key and the same nonce.

        The nonce must be shorter than the block size (it can have
        zero length; the counter is then as long as the block).

        If this parameter is not present, a random nonce will be created with
        length equal to half the block size. No random nonce shorter than
        64 bits will be created though - you must really think through all
        security consequences of using such a short block size.

      initial_value : posive integer or bytes/bytearray/memoryview
        The initial value for the counter. If not present, the cipher will
        start counting from 0. The value is incremented by one for each block.
        The counter number is encoded in big endian mode.

      counter : object
        Instance of ``Cryptodome.Util.Counter``, which allows full customization
        of the counter block. This parameter is incompatible to both ``nonce``
        and ``initial_value``.

    Any other keyword will be passed to the underlying block cipher.
    See the relevant documentation for details (at least ``key`` will need
    to be present).
    """

    cipher_state = factory._create_base_cipher(kwargs)

    counter = kwargs.pop("counter", None)
    nonce = kwargs.pop("nonce", None)
    initial_value = kwargs.pop("initial_value", None)
    if kwargs:
        raise TypeError("Invalid parameters for CTR mode: %s" % str(kwargs))

    if counter is not None and (nonce, initial_value) != (None, None):
        raise TypeError("'counter' and 'nonce'/'initial_value'"
                        " are mutually exclusive")

    if counter is None:
        # Cryptodome.Util.Counter is not used
        if nonce is None:
            if factory.block_size < 16:
                raise TypeError("Impossible to create a safe nonce for short"
                                " block sizes")
            nonce = get_random_bytes(factory.block_size // 2)
        else:
            if len(nonce) >= factory.block_size:
                raise ValueError("Nonce is too long")

        # What is not nonce is counter
        counter_len = factory.block_size - len(nonce)

        if initial_value is None:
            initial_value = 0

        if is_native_int(initial_value):
            if (1 << (counter_len * 8)) - 1 < initial_value:
                raise ValueError("Initial counter value is too large")
            initial_counter_block = nonce + long_to_bytes(
                initial_value, counter_len)
        else:
            if len(initial_value) != counter_len:
                raise ValueError(
                    "Incorrect length for counter byte string (%d bytes, expected %d)"
                    % (len(initial_value), counter_len))
            initial_counter_block = nonce + initial_value

        return CtrMode(
            cipher_state,
            initial_counter_block,
            len(nonce),  # prefix
            counter_len,
            False)  # little_endian

    # Cryptodome.Util.Counter is used

    # 'counter' used to be a callable object, but now it is
    # just a dictionary for backward compatibility.
    _counter = dict(counter)
    try:
        counter_len = _counter.pop("counter_len")
        prefix = _counter.pop("prefix")
        suffix = _counter.pop("suffix")
        initial_value = _counter.pop("initial_value")
        little_endian = _counter.pop("little_endian")
    except KeyError:
        raise TypeError("Incorrect counter object"
                        " (use Cryptodome.Util.Counter.new)")

    # Compute initial counter block
    words = []
    while initial_value > 0:
        words.append(struct.pack('B', initial_value & 255))
        initial_value >>= 8
    words += [b'\x00'] * max(0, counter_len - len(words))
    if not little_endian:
        words.reverse()
    initial_counter_block = prefix + b"".join(words) + suffix

    if len(initial_counter_block) != factory.block_size:
        raise ValueError("Size of the counter block (%d bytes) must match"
                         " block size (%d)" %
                         (len(initial_counter_block), factory.block_size))

    return CtrMode(cipher_state, initial_counter_block, len(prefix),
                   counter_len, little_endian)