slight update
This commit is contained in:
47
env/lib/python3.12/site-packages/Crypto/Math/Numbers.py
vendored
Normal file
47
env/lib/python3.12/site-packages/Crypto/Math/Numbers.py
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
__all__ = ["Integer"]
|
||||
|
||||
import os
|
||||
|
||||
try:
|
||||
if os.getenv("PYCRYPTODOME_DISABLE_GMP"):
|
||||
raise ImportError()
|
||||
|
||||
from Crypto.Math._IntegerGMP import IntegerGMP as Integer
|
||||
from Crypto.Math._IntegerGMP import implementation as _implementation
|
||||
except (ImportError, OSError, AttributeError):
|
||||
try:
|
||||
from Crypto.Math._IntegerCustom import IntegerCustom as Integer
|
||||
from Crypto.Math._IntegerCustom import implementation as _implementation
|
||||
except (ImportError, OSError):
|
||||
from Crypto.Math._IntegerNative import IntegerNative as Integer
|
||||
_implementation = {}
|
2
env/lib/python3.12/site-packages/Crypto/Math/Numbers.pyi
vendored
Normal file
2
env/lib/python3.12/site-packages/Crypto/Math/Numbers.pyi
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
from Crypto.Math._IntegerBase import IntegerBase as Integer
|
||||
__all__ = ['Integer']
|
369
env/lib/python3.12/site-packages/Crypto/Math/Primality.py
vendored
Normal file
369
env/lib/python3.12/site-packages/Crypto/Math/Primality.py
vendored
Normal file
@ -0,0 +1,369 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
"""Functions to create and test prime numbers.
|
||||
|
||||
:undocumented: __package__
|
||||
"""
|
||||
|
||||
from Crypto import Random
|
||||
from Crypto.Math.Numbers import Integer
|
||||
|
||||
from Crypto.Util.py3compat import iter_range
|
||||
|
||||
COMPOSITE = 0
|
||||
PROBABLY_PRIME = 1
|
||||
|
||||
|
||||
def miller_rabin_test(candidate, iterations, randfunc=None):
|
||||
"""Perform a Miller-Rabin primality test on an integer.
|
||||
|
||||
The test is specified in Section C.3.1 of `FIPS PUB 186-4`__.
|
||||
|
||||
:Parameters:
|
||||
candidate : integer
|
||||
The number to test for primality.
|
||||
iterations : integer
|
||||
The maximum number of iterations to perform before
|
||||
declaring a candidate a probable prime.
|
||||
randfunc : callable
|
||||
An RNG function where bases are taken from.
|
||||
|
||||
:Returns:
|
||||
``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``.
|
||||
|
||||
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
|
||||
"""
|
||||
|
||||
if not isinstance(candidate, Integer):
|
||||
candidate = Integer(candidate)
|
||||
|
||||
if candidate in (1, 2, 3, 5):
|
||||
return PROBABLY_PRIME
|
||||
|
||||
if candidate.is_even():
|
||||
return COMPOSITE
|
||||
|
||||
one = Integer(1)
|
||||
minus_one = Integer(candidate - 1)
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
# Step 1 and 2
|
||||
m = Integer(minus_one)
|
||||
a = 0
|
||||
while m.is_even():
|
||||
m >>= 1
|
||||
a += 1
|
||||
|
||||
# Skip step 3
|
||||
|
||||
# Step 4
|
||||
for i in iter_range(iterations):
|
||||
|
||||
# Step 4.1-2
|
||||
base = 1
|
||||
while base in (one, minus_one):
|
||||
base = Integer.random_range(min_inclusive=2,
|
||||
max_inclusive=candidate - 2,
|
||||
randfunc=randfunc)
|
||||
assert(2 <= base <= candidate - 2)
|
||||
|
||||
# Step 4.3-4.4
|
||||
z = pow(base, m, candidate)
|
||||
if z in (one, minus_one):
|
||||
continue
|
||||
|
||||
# Step 4.5
|
||||
for j in iter_range(1, a):
|
||||
z = pow(z, 2, candidate)
|
||||
if z == minus_one:
|
||||
break
|
||||
if z == one:
|
||||
return COMPOSITE
|
||||
else:
|
||||
return COMPOSITE
|
||||
|
||||
# Step 5
|
||||
return PROBABLY_PRIME
|
||||
|
||||
|
||||
def lucas_test(candidate):
|
||||
"""Perform a Lucas primality test on an integer.
|
||||
|
||||
The test is specified in Section C.3.3 of `FIPS PUB 186-4`__.
|
||||
|
||||
:Parameters:
|
||||
candidate : integer
|
||||
The number to test for primality.
|
||||
|
||||
:Returns:
|
||||
``Primality.COMPOSITE`` or ``Primality.PROBABLY_PRIME``.
|
||||
|
||||
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
|
||||
"""
|
||||
|
||||
if not isinstance(candidate, Integer):
|
||||
candidate = Integer(candidate)
|
||||
|
||||
# Step 1
|
||||
if candidate in (1, 2, 3, 5):
|
||||
return PROBABLY_PRIME
|
||||
if candidate.is_even() or candidate.is_perfect_square():
|
||||
return COMPOSITE
|
||||
|
||||
# Step 2
|
||||
def alternate():
|
||||
value = 5
|
||||
while True:
|
||||
yield value
|
||||
if value > 0:
|
||||
value += 2
|
||||
else:
|
||||
value -= 2
|
||||
value = -value
|
||||
|
||||
for D in alternate():
|
||||
if candidate in (D, -D):
|
||||
continue
|
||||
js = Integer.jacobi_symbol(D, candidate)
|
||||
if js == 0:
|
||||
return COMPOSITE
|
||||
if js == -1:
|
||||
break
|
||||
# Found D. P=1 and Q=(1-D)/4 (note that Q is guaranteed to be an integer)
|
||||
|
||||
# Step 3
|
||||
# This is \delta(n) = n - jacobi(D/n)
|
||||
K = candidate + 1
|
||||
# Step 4
|
||||
r = K.size_in_bits() - 1
|
||||
# Step 5
|
||||
# U_1=1 and V_1=P
|
||||
U_i = Integer(1)
|
||||
V_i = Integer(1)
|
||||
U_temp = Integer(0)
|
||||
V_temp = Integer(0)
|
||||
# Step 6
|
||||
for i in iter_range(r - 1, -1, -1):
|
||||
# Square
|
||||
# U_temp = U_i * V_i % candidate
|
||||
U_temp.set(U_i)
|
||||
U_temp *= V_i
|
||||
U_temp %= candidate
|
||||
# V_temp = (((V_i ** 2 + (U_i ** 2 * D)) * K) >> 1) % candidate
|
||||
V_temp.set(U_i)
|
||||
V_temp *= U_i
|
||||
V_temp *= D
|
||||
V_temp.multiply_accumulate(V_i, V_i)
|
||||
if V_temp.is_odd():
|
||||
V_temp += candidate
|
||||
V_temp >>= 1
|
||||
V_temp %= candidate
|
||||
# Multiply
|
||||
if K.get_bit(i):
|
||||
# U_i = (((U_temp + V_temp) * K) >> 1) % candidate
|
||||
U_i.set(U_temp)
|
||||
U_i += V_temp
|
||||
if U_i.is_odd():
|
||||
U_i += candidate
|
||||
U_i >>= 1
|
||||
U_i %= candidate
|
||||
# V_i = (((V_temp + U_temp * D) * K) >> 1) % candidate
|
||||
V_i.set(V_temp)
|
||||
V_i.multiply_accumulate(U_temp, D)
|
||||
if V_i.is_odd():
|
||||
V_i += candidate
|
||||
V_i >>= 1
|
||||
V_i %= candidate
|
||||
else:
|
||||
U_i.set(U_temp)
|
||||
V_i.set(V_temp)
|
||||
# Step 7
|
||||
if U_i == 0:
|
||||
return PROBABLY_PRIME
|
||||
return COMPOSITE
|
||||
|
||||
|
||||
from Crypto.Util.number import sieve_base as _sieve_base_large
|
||||
## The optimal number of small primes to use for the sieve
|
||||
## is probably dependent on the platform and the candidate size
|
||||
_sieve_base = set(_sieve_base_large[:100])
|
||||
|
||||
|
||||
def test_probable_prime(candidate, randfunc=None):
|
||||
"""Test if a number is prime.
|
||||
|
||||
A number is qualified as prime if it passes a certain
|
||||
number of Miller-Rabin tests (dependent on the size
|
||||
of the number, but such that probability of a false
|
||||
positive is less than 10^-30) and a single Lucas test.
|
||||
|
||||
For instance, a 1024-bit candidate will need to pass
|
||||
4 Miller-Rabin tests.
|
||||
|
||||
:Parameters:
|
||||
candidate : integer
|
||||
The number to test for primality.
|
||||
randfunc : callable
|
||||
The routine to draw random bytes from to select Miller-Rabin bases.
|
||||
:Returns:
|
||||
``PROBABLE_PRIME`` if the number if prime with very high probability.
|
||||
``COMPOSITE`` if the number is a composite.
|
||||
For efficiency reasons, ``COMPOSITE`` is also returned for small primes.
|
||||
"""
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
if not isinstance(candidate, Integer):
|
||||
candidate = Integer(candidate)
|
||||
|
||||
# First, check trial division by the smallest primes
|
||||
if int(candidate) in _sieve_base:
|
||||
return PROBABLY_PRIME
|
||||
try:
|
||||
map(candidate.fail_if_divisible_by, _sieve_base)
|
||||
except ValueError:
|
||||
return COMPOSITE
|
||||
|
||||
# These are the number of Miller-Rabin iterations s.t. p(k, t) < 1E-30,
|
||||
# with p(k, t) being the probability that a randomly chosen k-bit number
|
||||
# is composite but still survives t MR iterations.
|
||||
mr_ranges = ((220, 30), (280, 20), (390, 15), (512, 10),
|
||||
(620, 7), (740, 6), (890, 5), (1200, 4),
|
||||
(1700, 3), (3700, 2))
|
||||
|
||||
bit_size = candidate.size_in_bits()
|
||||
try:
|
||||
mr_iterations = list(filter(lambda x: bit_size < x[0],
|
||||
mr_ranges))[0][1]
|
||||
except IndexError:
|
||||
mr_iterations = 1
|
||||
|
||||
if miller_rabin_test(candidate, mr_iterations,
|
||||
randfunc=randfunc) == COMPOSITE:
|
||||
return COMPOSITE
|
||||
if lucas_test(candidate) == COMPOSITE:
|
||||
return COMPOSITE
|
||||
return PROBABLY_PRIME
|
||||
|
||||
|
||||
def generate_probable_prime(**kwargs):
|
||||
"""Generate a random probable prime.
|
||||
|
||||
The prime will not have any specific properties
|
||||
(e.g. it will not be a *strong* prime).
|
||||
|
||||
Random numbers are evaluated for primality until one
|
||||
passes all tests, consisting of a certain number of
|
||||
Miller-Rabin tests with random bases followed by
|
||||
a single Lucas test.
|
||||
|
||||
The number of Miller-Rabin iterations is chosen such that
|
||||
the probability that the output number is a non-prime is
|
||||
less than 1E-30 (roughly 2^{-100}).
|
||||
|
||||
This approach is compliant to `FIPS PUB 186-4`__.
|
||||
|
||||
:Keywords:
|
||||
exact_bits : integer
|
||||
The desired size in bits of the probable prime.
|
||||
It must be at least 160.
|
||||
randfunc : callable
|
||||
An RNG function where candidate primes are taken from.
|
||||
prime_filter : callable
|
||||
A function that takes an Integer as parameter and returns
|
||||
True if the number can be passed to further primality tests,
|
||||
False if it should be immediately discarded.
|
||||
|
||||
:Return:
|
||||
A probable prime in the range 2^exact_bits > p > 2^(exact_bits-1).
|
||||
|
||||
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
|
||||
"""
|
||||
|
||||
exact_bits = kwargs.pop("exact_bits", None)
|
||||
randfunc = kwargs.pop("randfunc", None)
|
||||
prime_filter = kwargs.pop("prime_filter", lambda x: True)
|
||||
if kwargs:
|
||||
raise ValueError("Unknown parameters: " + kwargs.keys())
|
||||
|
||||
if exact_bits is None:
|
||||
raise ValueError("Missing exact_bits parameter")
|
||||
if exact_bits < 160:
|
||||
raise ValueError("Prime number is not big enough.")
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
result = COMPOSITE
|
||||
while result == COMPOSITE:
|
||||
candidate = Integer.random(exact_bits=exact_bits,
|
||||
randfunc=randfunc) | 1
|
||||
if not prime_filter(candidate):
|
||||
continue
|
||||
result = test_probable_prime(candidate, randfunc)
|
||||
return candidate
|
||||
|
||||
|
||||
def generate_probable_safe_prime(**kwargs):
|
||||
"""Generate a random, probable safe prime.
|
||||
|
||||
Note this operation is much slower than generating a simple prime.
|
||||
|
||||
:Keywords:
|
||||
exact_bits : integer
|
||||
The desired size in bits of the probable safe prime.
|
||||
randfunc : callable
|
||||
An RNG function where candidate primes are taken from.
|
||||
|
||||
:Return:
|
||||
A probable safe prime in the range
|
||||
2^exact_bits > p > 2^(exact_bits-1).
|
||||
"""
|
||||
|
||||
exact_bits = kwargs.pop("exact_bits", None)
|
||||
randfunc = kwargs.pop("randfunc", None)
|
||||
if kwargs:
|
||||
raise ValueError("Unknown parameters: " + kwargs.keys())
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
result = COMPOSITE
|
||||
while result == COMPOSITE:
|
||||
q = generate_probable_prime(exact_bits=exact_bits - 1, randfunc=randfunc)
|
||||
candidate = q * 2 + 1
|
||||
if candidate.size_in_bits() != exact_bits:
|
||||
continue
|
||||
result = test_probable_prime(candidate, randfunc=randfunc)
|
||||
return candidate
|
18
env/lib/python3.12/site-packages/Crypto/Math/Primality.pyi
vendored
Normal file
18
env/lib/python3.12/site-packages/Crypto/Math/Primality.pyi
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
from typing import Callable, Optional, Union, Set
|
||||
|
||||
PrimeResult = int
|
||||
|
||||
COMPOSITE: PrimeResult
|
||||
PROBABLY_PRIME: PrimeResult
|
||||
|
||||
def miller_rabin_test(candidate: int, iterations: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ...
|
||||
def lucas_test(candidate: int) -> PrimeResult: ...
|
||||
_sieve_base: Set[int]
|
||||
def test_probable_prime(candidate: int, randfunc: Optional[Callable[[int],bytes]]=None) -> PrimeResult: ...
|
||||
def generate_probable_prime(*,
|
||||
exact_bits: int = ...,
|
||||
randfunc: Callable[[int],bytes] = ...,
|
||||
prime_filter: Callable[[int],bool] = ...) -> int: ...
|
||||
def generate_probable_safe_prime(*,
|
||||
exact_bits: int = ...,
|
||||
randfunc: Callable[[int],bytes] = ...) -> int: ...
|
412
env/lib/python3.12/site-packages/Crypto/Math/_IntegerBase.py
vendored
Normal file
412
env/lib/python3.12/site-packages/Crypto/Math/_IntegerBase.py
vendored
Normal file
@ -0,0 +1,412 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
import abc
|
||||
|
||||
from Crypto.Util.py3compat import iter_range, bord, bchr, ABC
|
||||
|
||||
from Crypto import Random
|
||||
|
||||
|
||||
class IntegerBase(ABC):
|
||||
|
||||
# Conversions
|
||||
@abc.abstractmethod
|
||||
def __int__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __str__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __repr__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def to_bytes(self, block_size=0, byteorder='big'):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def from_bytes(byte_string, byteorder='big'):
|
||||
pass
|
||||
|
||||
# Relations
|
||||
@abc.abstractmethod
|
||||
def __eq__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __ne__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __lt__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __le__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __gt__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __ge__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __nonzero__(self):
|
||||
pass
|
||||
__bool__ = __nonzero__
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_negative(self):
|
||||
pass
|
||||
|
||||
# Arithmetic operations
|
||||
@abc.abstractmethod
|
||||
def __add__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __sub__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __mul__(self, factor):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __floordiv__(self, divisor):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __mod__(self, divisor):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def inplace_pow(self, exponent, modulus=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __pow__(self, exponent, modulus=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __abs__(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def sqrt(self, modulus=None):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __iadd__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __isub__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __imul__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __imod__(self, term):
|
||||
pass
|
||||
|
||||
# Boolean/bit operations
|
||||
@abc.abstractmethod
|
||||
def __and__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __or__(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __rshift__(self, pos):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __irshift__(self, pos):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __lshift__(self, pos):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def __ilshift__(self, pos):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_bit(self, n):
|
||||
pass
|
||||
|
||||
# Extra
|
||||
@abc.abstractmethod
|
||||
def is_odd(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_even(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def size_in_bits(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def size_in_bytes(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_perfect_square(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def fail_if_divisible_by(self, small_prime):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def multiply_accumulate(self, a, b):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def set(self, source):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def inplace_inverse(self, modulus):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def inverse(self, modulus):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def gcd(self, term):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def lcm(self, term):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def jacobi_symbol(a, n):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _tonelli_shanks(n, p):
|
||||
"""Tonelli-shanks algorithm for computing the square root
|
||||
of n modulo a prime p.
|
||||
|
||||
n must be in the range [0..p-1].
|
||||
p must be at least even.
|
||||
|
||||
The return value r is the square root of modulo p. If non-zero,
|
||||
another solution will also exist (p-r).
|
||||
|
||||
Note we cannot assume that p is really a prime: if it's not,
|
||||
we can either raise an exception or return the correct value.
|
||||
"""
|
||||
|
||||
# See https://rosettacode.org/wiki/Tonelli-Shanks_algorithm
|
||||
|
||||
if n in (0, 1):
|
||||
return n
|
||||
|
||||
if p % 4 == 3:
|
||||
root = pow(n, (p + 1) // 4, p)
|
||||
if pow(root, 2, p) != n:
|
||||
raise ValueError("Cannot compute square root")
|
||||
return root
|
||||
|
||||
s = 1
|
||||
q = (p - 1) // 2
|
||||
while not (q & 1):
|
||||
s += 1
|
||||
q >>= 1
|
||||
|
||||
z = n.__class__(2)
|
||||
while True:
|
||||
euler = pow(z, (p - 1) // 2, p)
|
||||
if euler == 1:
|
||||
z += 1
|
||||
continue
|
||||
if euler == p - 1:
|
||||
break
|
||||
# Most probably p is not a prime
|
||||
raise ValueError("Cannot compute square root")
|
||||
|
||||
m = s
|
||||
c = pow(z, q, p)
|
||||
t = pow(n, q, p)
|
||||
r = pow(n, (q + 1) // 2, p)
|
||||
|
||||
while t != 1:
|
||||
for i in iter_range(0, m):
|
||||
if pow(t, 2**i, p) == 1:
|
||||
break
|
||||
if i == m:
|
||||
raise ValueError("Cannot compute square root of %d mod %d" % (n, p))
|
||||
b = pow(c, 2**(m - i - 1), p)
|
||||
m = i
|
||||
c = b**2 % p
|
||||
t = (t * b**2) % p
|
||||
r = (r * b) % p
|
||||
|
||||
if pow(r, 2, p) != n:
|
||||
raise ValueError("Cannot compute square root")
|
||||
|
||||
return r
|
||||
|
||||
@classmethod
|
||||
def random(cls, **kwargs):
|
||||
"""Generate a random natural integer of a certain size.
|
||||
|
||||
:Keywords:
|
||||
exact_bits : positive integer
|
||||
The length in bits of the resulting random Integer number.
|
||||
The number is guaranteed to fulfil the relation:
|
||||
|
||||
2^bits > result >= 2^(bits - 1)
|
||||
|
||||
max_bits : positive integer
|
||||
The maximum length in bits of the resulting random Integer number.
|
||||
The number is guaranteed to fulfil the relation:
|
||||
|
||||
2^bits > result >=0
|
||||
|
||||
randfunc : callable
|
||||
A function that returns a random byte string. The length of the
|
||||
byte string is passed as parameter. Optional.
|
||||
If not provided (or ``None``), randomness is read from the system RNG.
|
||||
|
||||
:Return: a Integer object
|
||||
"""
|
||||
|
||||
exact_bits = kwargs.pop("exact_bits", None)
|
||||
max_bits = kwargs.pop("max_bits", None)
|
||||
randfunc = kwargs.pop("randfunc", None)
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
if exact_bits is None and max_bits is None:
|
||||
raise ValueError("Either 'exact_bits' or 'max_bits' must be specified")
|
||||
|
||||
if exact_bits is not None and max_bits is not None:
|
||||
raise ValueError("'exact_bits' and 'max_bits' are mutually exclusive")
|
||||
|
||||
bits = exact_bits or max_bits
|
||||
bytes_needed = ((bits - 1) // 8) + 1
|
||||
significant_bits_msb = 8 - (bytes_needed * 8 - bits)
|
||||
msb = bord(randfunc(1)[0])
|
||||
if exact_bits is not None:
|
||||
msb |= 1 << (significant_bits_msb - 1)
|
||||
msb &= (1 << significant_bits_msb) - 1
|
||||
|
||||
return cls.from_bytes(bchr(msb) + randfunc(bytes_needed - 1))
|
||||
|
||||
@classmethod
|
||||
def random_range(cls, **kwargs):
|
||||
"""Generate a random integer within a given internal.
|
||||
|
||||
:Keywords:
|
||||
min_inclusive : integer
|
||||
The lower end of the interval (inclusive).
|
||||
max_inclusive : integer
|
||||
The higher end of the interval (inclusive).
|
||||
max_exclusive : integer
|
||||
The higher end of the interval (exclusive).
|
||||
randfunc : callable
|
||||
A function that returns a random byte string. The length of the
|
||||
byte string is passed as parameter. Optional.
|
||||
If not provided (or ``None``), randomness is read from the system RNG.
|
||||
:Returns:
|
||||
An Integer randomly taken in the given interval.
|
||||
"""
|
||||
|
||||
min_inclusive = kwargs.pop("min_inclusive", None)
|
||||
max_inclusive = kwargs.pop("max_inclusive", None)
|
||||
max_exclusive = kwargs.pop("max_exclusive", None)
|
||||
randfunc = kwargs.pop("randfunc", None)
|
||||
|
||||
if kwargs:
|
||||
raise ValueError("Unknown keywords: " + str(kwargs.keys))
|
||||
if None not in (max_inclusive, max_exclusive):
|
||||
raise ValueError("max_inclusive and max_exclusive cannot be both"
|
||||
" specified")
|
||||
if max_exclusive is not None:
|
||||
max_inclusive = max_exclusive - 1
|
||||
if None in (min_inclusive, max_inclusive):
|
||||
raise ValueError("Missing keyword to identify the interval")
|
||||
|
||||
if randfunc is None:
|
||||
randfunc = Random.new().read
|
||||
|
||||
norm_maximum = max_inclusive - min_inclusive
|
||||
bits_needed = cls(norm_maximum).size_in_bits()
|
||||
|
||||
norm_candidate = -1
|
||||
while not 0 <= norm_candidate <= norm_maximum:
|
||||
norm_candidate = cls.random(
|
||||
max_bits=bits_needed,
|
||||
randfunc=randfunc
|
||||
)
|
||||
return norm_candidate + min_inclusive
|
||||
|
||||
@staticmethod
|
||||
@abc.abstractmethod
|
||||
def _mult_modulo_bytes(term1, term2, modulus):
|
||||
"""Multiply two integers, take the modulo, and encode as big endian.
|
||||
This specialized method is used for RSA decryption.
|
||||
|
||||
Args:
|
||||
term1 : integer
|
||||
The first term of the multiplication, non-negative.
|
||||
term2 : integer
|
||||
The second term of the multiplication, non-negative.
|
||||
modulus: integer
|
||||
The modulus, a positive odd number.
|
||||
:Returns:
|
||||
A byte string, with the result of the modular multiplication
|
||||
encoded in big endian mode.
|
||||
It is as long as the modulus would be, with zero padding
|
||||
on the left if needed.
|
||||
"""
|
||||
pass
|
67
env/lib/python3.12/site-packages/Crypto/Math/_IntegerBase.pyi
vendored
Normal file
67
env/lib/python3.12/site-packages/Crypto/Math/_IntegerBase.pyi
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
from typing import Optional, Union, Callable
|
||||
|
||||
RandFunc = Callable[[int],int]
|
||||
|
||||
class IntegerBase:
|
||||
|
||||
def __init__(self, value: Union[IntegerBase, int]): ...
|
||||
|
||||
def __int__(self) -> int: ...
|
||||
def __str__(self) -> str: ...
|
||||
def __repr__(self) -> str: ...
|
||||
def to_bytes(self, block_size: Optional[int]=0, byteorder: str= ...) -> bytes: ...
|
||||
@staticmethod
|
||||
def from_bytes(byte_string: bytes, byteorder: Optional[str] = ...) -> IntegerBase: ...
|
||||
def __eq__(self, term: object) -> bool: ...
|
||||
def __ne__(self, term: object) -> bool: ...
|
||||
def __lt__(self, term: Union[IntegerBase, int]) -> bool: ...
|
||||
def __le__(self, term: Union[IntegerBase, int]) -> bool: ...
|
||||
def __gt__(self, term: Union[IntegerBase, int]) -> bool: ...
|
||||
def __ge__(self, term: Union[IntegerBase, int]) -> bool: ...
|
||||
def __nonzero__(self) -> bool: ...
|
||||
def is_negative(self) -> bool: ...
|
||||
def __add__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __sub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __mul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __floordiv__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __mod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def inplace_pow(self, exponent: int, modulus: Optional[Union[IntegerBase, int]]=None) -> IntegerBase: ...
|
||||
def __pow__(self, exponent: int, modulus: Optional[int]) -> IntegerBase: ...
|
||||
def __abs__(self) -> IntegerBase: ...
|
||||
def sqrt(self, modulus: Optional[int]) -> IntegerBase: ...
|
||||
def __iadd__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __isub__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __imul__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __imod__(self, divisor: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __and__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __or__(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __rshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __irshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __lshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def __ilshift__(self, pos: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def get_bit(self, n: int) -> bool: ...
|
||||
def is_odd(self) -> bool: ...
|
||||
def is_even(self) -> bool: ...
|
||||
def size_in_bits(self) -> int: ...
|
||||
def size_in_bytes(self) -> int: ...
|
||||
def is_perfect_square(self) -> bool: ...
|
||||
def fail_if_divisible_by(self, small_prime: Union[IntegerBase, int]) -> None: ...
|
||||
def multiply_accumulate(self, a: Union[IntegerBase, int], b: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def set(self, source: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def inplace_inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def inverse(self, modulus: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def gcd(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
def lcm(self, term: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
@staticmethod
|
||||
def jacobi_symbol(a: Union[IntegerBase, int], n: Union[IntegerBase, int]) -> IntegerBase: ...
|
||||
@staticmethod
|
||||
def _tonelli_shanks(n: Union[IntegerBase, int], p: Union[IntegerBase, int]) -> IntegerBase : ...
|
||||
@classmethod
|
||||
def random(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ...
|
||||
@classmethod
|
||||
def random_range(cls, **kwargs: Union[int,RandFunc]) -> IntegerBase : ...
|
||||
@staticmethod
|
||||
def _mult_modulo_bytes(term1: Union[IntegerBase, int],
|
||||
term2: Union[IntegerBase, int],
|
||||
modulus: Union[IntegerBase, int]) -> bytes: ...
|
||||
|
162
env/lib/python3.12/site-packages/Crypto/Math/_IntegerCustom.py
vendored
Normal file
162
env/lib/python3.12/site-packages/Crypto/Math/_IntegerCustom.py
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from ._IntegerNative import IntegerNative
|
||||
|
||||
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||
|
||||
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
|
||||
create_string_buffer,
|
||||
get_raw_buffer, backend,
|
||||
c_size_t, c_ulonglong)
|
||||
|
||||
|
||||
from Crypto.Random.random import getrandbits
|
||||
|
||||
c_defs = """
|
||||
int monty_pow(uint8_t *out,
|
||||
const uint8_t *base,
|
||||
const uint8_t *exp,
|
||||
const uint8_t *modulus,
|
||||
size_t len,
|
||||
uint64_t seed);
|
||||
|
||||
int monty_multiply(uint8_t *out,
|
||||
const uint8_t *term1,
|
||||
const uint8_t *term2,
|
||||
const uint8_t *modulus,
|
||||
size_t len);
|
||||
"""
|
||||
|
||||
|
||||
_raw_montgomery = load_pycryptodome_raw_lib("Crypto.Math._modexp", c_defs)
|
||||
implementation = {"library": "custom", "api": backend}
|
||||
|
||||
|
||||
class IntegerCustom(IntegerNative):
|
||||
|
||||
@staticmethod
|
||||
def from_bytes(byte_string, byteorder='big'):
|
||||
if byteorder == 'big':
|
||||
pass
|
||||
elif byteorder == 'little':
|
||||
byte_string = bytearray(byte_string)
|
||||
byte_string.reverse()
|
||||
else:
|
||||
raise ValueError("Incorrect byteorder")
|
||||
return IntegerCustom(bytes_to_long(byte_string))
|
||||
|
||||
def inplace_pow(self, exponent, modulus=None):
|
||||
exp_value = int(exponent)
|
||||
if exp_value < 0:
|
||||
raise ValueError("Exponent must not be negative")
|
||||
|
||||
# No modular reduction
|
||||
if modulus is None:
|
||||
self._value = pow(self._value, exp_value)
|
||||
return self
|
||||
|
||||
# With modular reduction
|
||||
mod_value = int(modulus)
|
||||
if mod_value < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
if mod_value == 0:
|
||||
raise ZeroDivisionError("Modulus cannot be zero")
|
||||
|
||||
# C extension only works with odd moduli
|
||||
if (mod_value & 1) == 0:
|
||||
self._value = pow(self._value, exp_value, mod_value)
|
||||
return self
|
||||
|
||||
# C extension only works with bases smaller than modulus
|
||||
if self._value >= mod_value:
|
||||
self._value %= mod_value
|
||||
|
||||
max_len = len(long_to_bytes(max(self._value, exp_value, mod_value)))
|
||||
|
||||
base_b = long_to_bytes(self._value, max_len)
|
||||
exp_b = long_to_bytes(exp_value, max_len)
|
||||
modulus_b = long_to_bytes(mod_value, max_len)
|
||||
|
||||
out = create_string_buffer(max_len)
|
||||
|
||||
error = _raw_montgomery.monty_pow(
|
||||
out,
|
||||
base_b,
|
||||
exp_b,
|
||||
modulus_b,
|
||||
c_size_t(max_len),
|
||||
c_ulonglong(getrandbits(64))
|
||||
)
|
||||
|
||||
if error:
|
||||
raise ValueError("monty_pow failed with error: %d" % error)
|
||||
|
||||
result = bytes_to_long(get_raw_buffer(out))
|
||||
self._value = result
|
||||
return self
|
||||
|
||||
@staticmethod
|
||||
def _mult_modulo_bytes(term1, term2, modulus):
|
||||
|
||||
# With modular reduction
|
||||
mod_value = int(modulus)
|
||||
if mod_value < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
if mod_value == 0:
|
||||
raise ZeroDivisionError("Modulus cannot be zero")
|
||||
|
||||
# C extension only works with odd moduli
|
||||
if (mod_value & 1) == 0:
|
||||
raise ValueError("Odd modulus is required")
|
||||
|
||||
# C extension only works with non-negative terms smaller than modulus
|
||||
if term1 >= mod_value or term1 < 0:
|
||||
term1 %= mod_value
|
||||
if term2 >= mod_value or term2 < 0:
|
||||
term2 %= mod_value
|
||||
|
||||
modulus_b = long_to_bytes(mod_value)
|
||||
numbers_len = len(modulus_b)
|
||||
term1_b = long_to_bytes(term1, numbers_len)
|
||||
term2_b = long_to_bytes(term2, numbers_len)
|
||||
out = create_string_buffer(numbers_len)
|
||||
|
||||
error = _raw_montgomery.monty_multiply(
|
||||
out,
|
||||
term1_b,
|
||||
term2_b,
|
||||
modulus_b,
|
||||
c_size_t(numbers_len)
|
||||
)
|
||||
if error:
|
||||
raise ValueError("monty_multiply failed with error: %d" % error)
|
||||
|
||||
return get_raw_buffer(out)
|
8
env/lib/python3.12/site-packages/Crypto/Math/_IntegerCustom.pyi
vendored
Normal file
8
env/lib/python3.12/site-packages/Crypto/Math/_IntegerCustom.pyi
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
from typing import Any
|
||||
|
||||
from ._IntegerNative import IntegerNative
|
||||
|
||||
_raw_montgomery = Any
|
||||
|
||||
class IntegerCustom(IntegerNative):
|
||||
pass
|
799
env/lib/python3.12/site-packages/Crypto/Math/_IntegerGMP.py
vendored
Normal file
799
env/lib/python3.12/site-packages/Crypto/Math/_IntegerGMP.py
vendored
Normal file
@ -0,0 +1,799 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
import sys
|
||||
import struct
|
||||
|
||||
from Crypto.Util.py3compat import is_native_int
|
||||
|
||||
from Crypto.Util._raw_api import (backend, load_lib,
|
||||
c_ulong, c_size_t, c_uint8_ptr)
|
||||
|
||||
from ._IntegerBase import IntegerBase
|
||||
|
||||
gmp_defs = """typedef unsigned long UNIX_ULONG;
|
||||
typedef struct { int a; int b; void *c; } MPZ;
|
||||
typedef MPZ mpz_t[1];
|
||||
typedef UNIX_ULONG mp_bitcnt_t;
|
||||
|
||||
void __gmpz_init (mpz_t x);
|
||||
void __gmpz_init_set (mpz_t rop, const mpz_t op);
|
||||
void __gmpz_init_set_ui (mpz_t rop, UNIX_ULONG op);
|
||||
|
||||
UNIX_ULONG __gmpz_get_ui (const mpz_t op);
|
||||
void __gmpz_set (mpz_t rop, const mpz_t op);
|
||||
void __gmpz_set_ui (mpz_t rop, UNIX_ULONG op);
|
||||
void __gmpz_add (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_add_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
|
||||
void __gmpz_sub_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
|
||||
void __gmpz_addmul (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_addmul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
|
||||
void __gmpz_submul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
|
||||
void __gmpz_import (mpz_t rop, size_t count, int order, size_t size,
|
||||
int endian, size_t nails, const void *op);
|
||||
void * __gmpz_export (void *rop, size_t *countp, int order,
|
||||
size_t size,
|
||||
int endian, size_t nails, const mpz_t op);
|
||||
size_t __gmpz_sizeinbase (const mpz_t op, int base);
|
||||
void __gmpz_sub (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_mul (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_mul_ui (mpz_t rop, const mpz_t op1, UNIX_ULONG op2);
|
||||
int __gmpz_cmp (const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_powm (mpz_t rop, const mpz_t base, const mpz_t exp, const
|
||||
mpz_t mod);
|
||||
void __gmpz_powm_ui (mpz_t rop, const mpz_t base, UNIX_ULONG exp,
|
||||
const mpz_t mod);
|
||||
void __gmpz_pow_ui (mpz_t rop, const mpz_t base, UNIX_ULONG exp);
|
||||
void __gmpz_sqrt(mpz_t rop, const mpz_t op);
|
||||
void __gmpz_mod (mpz_t r, const mpz_t n, const mpz_t d);
|
||||
void __gmpz_neg (mpz_t rop, const mpz_t op);
|
||||
void __gmpz_abs (mpz_t rop, const mpz_t op);
|
||||
void __gmpz_and (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_ior (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
void __gmpz_clear (mpz_t x);
|
||||
void __gmpz_tdiv_q_2exp (mpz_t q, const mpz_t n, mp_bitcnt_t b);
|
||||
void __gmpz_fdiv_q (mpz_t q, const mpz_t n, const mpz_t d);
|
||||
void __gmpz_mul_2exp (mpz_t rop, const mpz_t op1, mp_bitcnt_t op2);
|
||||
int __gmpz_tstbit (const mpz_t op, mp_bitcnt_t bit_index);
|
||||
int __gmpz_perfect_square_p (const mpz_t op);
|
||||
int __gmpz_jacobi (const mpz_t a, const mpz_t b);
|
||||
void __gmpz_gcd (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
UNIX_ULONG __gmpz_gcd_ui (mpz_t rop, const mpz_t op1,
|
||||
UNIX_ULONG op2);
|
||||
void __gmpz_lcm (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
int __gmpz_invert (mpz_t rop, const mpz_t op1, const mpz_t op2);
|
||||
int __gmpz_divisible_p (const mpz_t n, const mpz_t d);
|
||||
int __gmpz_divisible_ui_p (const mpz_t n, UNIX_ULONG d);
|
||||
|
||||
size_t __gmpz_size (const mpz_t op);
|
||||
UNIX_ULONG __gmpz_getlimbn (const mpz_t op, size_t n);
|
||||
"""
|
||||
|
||||
if sys.platform == "win32":
|
||||
raise ImportError("Not using GMP on Windows")
|
||||
|
||||
lib = load_lib("gmp", gmp_defs)
|
||||
implementation = {"library": "gmp", "api": backend}
|
||||
|
||||
if hasattr(lib, "__mpir_version"):
|
||||
raise ImportError("MPIR library detected")
|
||||
|
||||
|
||||
# Lazy creation of GMP methods
|
||||
class _GMP(object):
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name.startswith("mpz_"):
|
||||
func_name = "__gmpz_" + name[4:]
|
||||
elif name.startswith("gmp_"):
|
||||
func_name = "__gmp_" + name[4:]
|
||||
else:
|
||||
raise AttributeError("Attribute %s is invalid" % name)
|
||||
func = getattr(lib, func_name)
|
||||
setattr(self, name, func)
|
||||
return func
|
||||
|
||||
|
||||
_gmp = _GMP()
|
||||
|
||||
|
||||
# In order to create a function that returns a pointer to
|
||||
# a new MPZ structure, we need to break the abstraction
|
||||
# and know exactly what ffi backend we have
|
||||
if implementation["api"] == "ctypes":
|
||||
from ctypes import Structure, c_int, c_void_p, byref
|
||||
|
||||
class _MPZ(Structure):
|
||||
_fields_ = [('_mp_alloc', c_int),
|
||||
('_mp_size', c_int),
|
||||
('_mp_d', c_void_p)]
|
||||
|
||||
def new_mpz():
|
||||
return byref(_MPZ())
|
||||
|
||||
_gmp.mpz_getlimbn.restype = c_ulong
|
||||
|
||||
else:
|
||||
# We are using CFFI
|
||||
from Crypto.Util._raw_api import ffi
|
||||
|
||||
def new_mpz():
|
||||
return ffi.new("MPZ*")
|
||||
|
||||
|
||||
# Size of a native word
|
||||
_sys_bits = 8 * struct.calcsize("P")
|
||||
|
||||
|
||||
class IntegerGMP(IntegerBase):
|
||||
"""A fast, arbitrary precision integer"""
|
||||
|
||||
_zero_mpz_p = new_mpz()
|
||||
_gmp.mpz_init_set_ui(_zero_mpz_p, c_ulong(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
|
||||
|
||||
# Conversions
|
||||
def __int__(self):
|
||||
tmp = new_mpz()
|
||||
_gmp.mpz_init_set(tmp, self._mpz_p)
|
||||
|
||||
try:
|
||||
value = 0
|
||||
slot = 0
|
||||
while _gmp.mpz_cmp(tmp, self._zero_mpz_p) != 0:
|
||||
lsb = _gmp.mpz_get_ui(tmp) & 0xFFFFFFFF
|
||||
value |= lsb << (slot * 32)
|
||||
_gmp.mpz_tdiv_q_2exp(tmp, tmp, c_ulong(32))
|
||||
slot = slot + 1
|
||||
finally:
|
||||
_gmp.mpz_clear(tmp)
|
||||
|
||||
if self < 0:
|
||||
value = -value
|
||||
return int(value)
|
||||
|
||||
def __str__(self):
|
||||
return str(int(self))
|
||||
|
||||
def __repr__(self):
|
||||
return "Integer(%s)" % str(self)
|
||||
|
||||
# Only Python 2.x
|
||||
def __hex__(self):
|
||||
return hex(int(self))
|
||||
|
||||
# Only Python 3.x
|
||||
def __index__(self):
|
||||
return int(self)
|
||||
|
||||
def to_bytes(self, block_size=0, byteorder='big'):
|
||||
"""Convert the number into a byte string.
|
||||
|
||||
This method encodes the number in network order and prepends
|
||||
as many zero bytes as required. It only works for non-negative
|
||||
values.
|
||||
|
||||
:Parameters:
|
||||
block_size : integer
|
||||
The exact size the output byte string must have.
|
||||
If zero, the string has the minimal length.
|
||||
byteorder : string
|
||||
'big' for big-endian integers (default), 'little' for litte-endian.
|
||||
:Returns:
|
||||
A byte string.
|
||||
:Raise ValueError:
|
||||
If the value is negative or if ``block_size`` is
|
||||
provided and the length of the byte string would exceed it.
|
||||
"""
|
||||
|
||||
if self < 0:
|
||||
raise ValueError("Conversion only valid for non-negative numbers")
|
||||
|
||||
num_limbs = _gmp.mpz_size(self._mpz_p)
|
||||
if _sys_bits == 32:
|
||||
spchar = "L"
|
||||
num_limbs = max(1, num_limbs, (block_size + 3) // 4)
|
||||
elif _sys_bits == 64:
|
||||
spchar = "Q"
|
||||
num_limbs = max(1, num_limbs, (block_size + 7) // 8)
|
||||
else:
|
||||
raise ValueError("Unknown limb size")
|
||||
|
||||
# mpz_getlimbn returns 0 if i is larger than the number of actual limbs
|
||||
limbs = [_gmp.mpz_getlimbn(self._mpz_p, num_limbs - i - 1) for i in range(num_limbs)]
|
||||
|
||||
result = struct.pack(">" + spchar * num_limbs, *limbs)
|
||||
cutoff_len = len(result) - block_size
|
||||
if block_size == 0:
|
||||
result = result.lstrip(b'\x00')
|
||||
elif cutoff_len > 0:
|
||||
if result[:cutoff_len] != b'\x00' * (cutoff_len):
|
||||
raise ValueError("Number is too big to convert to "
|
||||
"byte string of prescribed length")
|
||||
result = result[cutoff_len:]
|
||||
elif cutoff_len < 0:
|
||||
result = b'\x00' * (-cutoff_len) + result
|
||||
|
||||
if byteorder == 'little':
|
||||
result = result[::-1]
|
||||
elif byteorder == 'big':
|
||||
pass
|
||||
else:
|
||||
raise ValueError("Incorrect byteorder")
|
||||
|
||||
if len(result) == 0:
|
||||
result = b'\x00'
|
||||
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def from_bytes(byte_string, byteorder='big'):
|
||||
"""Convert a byte string into a number.
|
||||
|
||||
:Parameters:
|
||||
byte_string : byte string
|
||||
The input number, encoded in network order.
|
||||
It can only be non-negative.
|
||||
byteorder : string
|
||||
'big' for big-endian integers (default), 'little' for litte-endian.
|
||||
|
||||
:Return:
|
||||
The ``Integer`` object carrying the same value as the input.
|
||||
"""
|
||||
result = IntegerGMP(0)
|
||||
if byteorder == 'big':
|
||||
pass
|
||||
elif byteorder == 'little':
|
||||
byte_string = bytearray(byte_string)
|
||||
byte_string.reverse()
|
||||
else:
|
||||
raise ValueError("Incorrect byteorder")
|
||||
_gmp.mpz_import(
|
||||
result._mpz_p,
|
||||
c_size_t(len(byte_string)), # Amount of words to read
|
||||
1, # Big endian
|
||||
c_size_t(1), # Each word is 1 byte long
|
||||
0, # Endianess within a word - not relevant
|
||||
c_size_t(0), # No nails
|
||||
c_uint8_ptr(byte_string))
|
||||
return result
|
||||
|
||||
# Relations
|
||||
def _apply_and_return(self, func, term):
|
||||
if not isinstance(term, IntegerGMP):
|
||||
term = IntegerGMP(term)
|
||||
return func(self._mpz_p, term._mpz_p)
|
||||
|
||||
def __eq__(self, term):
|
||||
if not (isinstance(term, IntegerGMP) or is_native_int(term)):
|
||||
return False
|
||||
return self._apply_and_return(_gmp.mpz_cmp, term) == 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
|
||||
|
||||
def __lt__(self, term):
|
||||
return self._apply_and_return(_gmp.mpz_cmp, term) < 0
|
||||
|
||||
def __le__(self, term):
|
||||
return self._apply_and_return(_gmp.mpz_cmp, term) <= 0
|
||||
|
||||
def __gt__(self, term):
|
||||
return self._apply_and_return(_gmp.mpz_cmp, term) > 0
|
||||
|
||||
def __ge__(self, term):
|
||||
return self._apply_and_return(_gmp.mpz_cmp, term) >= 0
|
||||
|
||||
def __nonzero__(self):
|
||||
return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) != 0
|
||||
__bool__ = __nonzero__
|
||||
|
||||
def is_negative(self):
|
||||
return _gmp.mpz_cmp(self._mpz_p, self._zero_mpz_p) < 0
|
||||
|
||||
# Arithmetic operations
|
||||
def __add__(self, term):
|
||||
result = IntegerGMP(0)
|
||||
if not isinstance(term, IntegerGMP):
|
||||
try:
|
||||
term = IntegerGMP(term)
|
||||
except NotImplementedError:
|
||||
return NotImplemented
|
||||
_gmp.mpz_add(result._mpz_p,
|
||||
self._mpz_p,
|
||||
term._mpz_p)
|
||||
return result
|
||||
|
||||
def __sub__(self, term):
|
||||
result = IntegerGMP(0)
|
||||
if not isinstance(term, IntegerGMP):
|
||||
try:
|
||||
term = IntegerGMP(term)
|
||||
except NotImplementedError:
|
||||
return NotImplemented
|
||||
_gmp.mpz_sub(result._mpz_p,
|
||||
self._mpz_p,
|
||||
term._mpz_p)
|
||||
return result
|
||||
|
||||
def __mul__(self, term):
|
||||
result = IntegerGMP(0)
|
||||
if not isinstance(term, IntegerGMP):
|
||||
try:
|
||||
term = IntegerGMP(term)
|
||||
except NotImplementedError:
|
||||
return NotImplemented
|
||||
_gmp.mpz_mul(result._mpz_p,
|
||||
self._mpz_p,
|
||||
term._mpz_p)
|
||||
return result
|
||||
|
||||
def __floordiv__(self, divisor):
|
||||
if not isinstance(divisor, IntegerGMP):
|
||||
divisor = IntegerGMP(divisor)
|
||||
if _gmp.mpz_cmp(divisor._mpz_p,
|
||||
self._zero_mpz_p) == 0:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
result = IntegerGMP(0)
|
||||
_gmp.mpz_fdiv_q(result._mpz_p,
|
||||
self._mpz_p,
|
||||
divisor._mpz_p)
|
||||
return result
|
||||
|
||||
def __mod__(self, divisor):
|
||||
if not isinstance(divisor, IntegerGMP):
|
||||
divisor = IntegerGMP(divisor)
|
||||
comp = _gmp.mpz_cmp(divisor._mpz_p,
|
||||
self._zero_mpz_p)
|
||||
if comp == 0:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
if comp < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
result = IntegerGMP(0)
|
||||
_gmp.mpz_mod(result._mpz_p,
|
||||
self._mpz_p,
|
||||
divisor._mpz_p)
|
||||
return result
|
||||
|
||||
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
|
||||
|
||||
def __pow__(self, exponent, modulus=None):
|
||||
result = IntegerGMP(self)
|
||||
return result.inplace_pow(exponent, modulus)
|
||||
|
||||
def __abs__(self):
|
||||
result = IntegerGMP(0)
|
||||
_gmp.mpz_abs(result._mpz_p, self._mpz_p)
|
||||
return result
|
||||
|
||||
def sqrt(self, modulus=None):
|
||||
"""Return the largest Integer that does not
|
||||
exceed the square root"""
|
||||
|
||||
if modulus is None:
|
||||
if self < 0:
|
||||
raise ValueError("Square root of negative value")
|
||||
result = IntegerGMP(0)
|
||||
_gmp.mpz_sqrt(result._mpz_p,
|
||||
self._mpz_p)
|
||||
else:
|
||||
if modulus <= 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
modulus = int(modulus)
|
||||
result = IntegerGMP(self._tonelli_shanks(int(self) % modulus, modulus))
|
||||
|
||||
return result
|
||||
|
||||
def __iadd__(self, term):
|
||||
if is_native_int(term):
|
||||
if 0 <= term < 65536:
|
||||
_gmp.mpz_add_ui(self._mpz_p,
|
||||
self._mpz_p,
|
||||
c_ulong(term))
|
||||
return self
|
||||
if -65535 < term < 0:
|
||||
_gmp.mpz_sub_ui(self._mpz_p,
|
||||
self._mpz_p,
|
||||
c_ulong(-term))
|
||||
return self
|
||||
term = IntegerGMP(term)
|
||||
_gmp.mpz_add(self._mpz_p,
|
||||
self._mpz_p,
|
||||
term._mpz_p)
|
||||
return self
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
def __imod__(self, divisor):
|
||||
if not isinstance(divisor, IntegerGMP):
|
||||
divisor = IntegerGMP(divisor)
|
||||
comp = _gmp.mpz_cmp(divisor._mpz_p,
|
||||
divisor._zero_mpz_p)
|
||||
if comp == 0:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
if comp < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
_gmp.mpz_mod(self._mpz_p,
|
||||
self._mpz_p,
|
||||
divisor._mpz_p)
|
||||
return self
|
||||
|
||||
# Boolean/bit operations
|
||||
def __and__(self, term):
|
||||
result = IntegerGMP(0)
|
||||
if not isinstance(term, IntegerGMP):
|
||||
term = IntegerGMP(term)
|
||||
_gmp.mpz_and(result._mpz_p,
|
||||
self._mpz_p,
|
||||
term._mpz_p)
|
||||
return result
|
||||
|
||||
def __or__(self, term):
|
||||
result = IntegerGMP(0)
|
||||
if not isinstance(term, IntegerGMP):
|
||||
term = IntegerGMP(term)
|
||||
_gmp.mpz_ior(result._mpz_p,
|
||||
self._mpz_p,
|
||||
term._mpz_p)
|
||||
return result
|
||||
|
||||
def __rshift__(self, pos):
|
||||
result = IntegerGMP(0)
|
||||
if pos < 0:
|
||||
raise ValueError("negative shift count")
|
||||
if pos > 65536:
|
||||
if self < 0:
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
_gmp.mpz_tdiv_q_2exp(result._mpz_p,
|
||||
self._mpz_p,
|
||||
c_ulong(int(pos)))
|
||||
return result
|
||||
|
||||
def __irshift__(self, pos):
|
||||
if pos < 0:
|
||||
raise ValueError("negative shift count")
|
||||
if pos > 65536:
|
||||
if self < 0:
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
_gmp.mpz_tdiv_q_2exp(self._mpz_p,
|
||||
self._mpz_p,
|
||||
c_ulong(int(pos)))
|
||||
return self
|
||||
|
||||
def __lshift__(self, pos):
|
||||
result = IntegerGMP(0)
|
||||
if not 0 <= pos < 65536:
|
||||
raise ValueError("Incorrect shift count")
|
||||
_gmp.mpz_mul_2exp(result._mpz_p,
|
||||
self._mpz_p,
|
||||
c_ulong(int(pos)))
|
||||
return result
|
||||
|
||||
def __ilshift__(self, pos):
|
||||
if not 0 <= pos < 65536:
|
||||
raise ValueError("Incorrect shift count")
|
||||
_gmp.mpz_mul_2exp(self._mpz_p,
|
||||
self._mpz_p,
|
||||
c_ulong(int(pos)))
|
||||
return self
|
||||
|
||||
def get_bit(self, n):
|
||||
"""Return True if the n-th bit is set to 1.
|
||||
Bit 0 is the least significant."""
|
||||
|
||||
if self < 0:
|
||||
raise ValueError("no bit representation for negative values")
|
||||
if n < 0:
|
||||
raise ValueError("negative bit count")
|
||||
if n > 65536:
|
||||
return 0
|
||||
return bool(_gmp.mpz_tstbit(self._mpz_p,
|
||||
c_ulong(int(n))))
|
||||
|
||||
# Extra
|
||||
def is_odd(self):
|
||||
return _gmp.mpz_tstbit(self._mpz_p, 0) == 1
|
||||
|
||||
def is_even(self):
|
||||
return _gmp.mpz_tstbit(self._mpz_p, 0) == 0
|
||||
|
||||
def size_in_bits(self):
|
||||
"""Return the minimum number of bits that can encode the number."""
|
||||
|
||||
if self < 0:
|
||||
raise ValueError("Conversion only valid for non-negative numbers")
|
||||
return _gmp.mpz_sizeinbase(self._mpz_p, 2)
|
||||
|
||||
def size_in_bytes(self):
|
||||
"""Return the minimum number of bytes that can encode the number."""
|
||||
return (self.size_in_bits() - 1) // 8 + 1
|
||||
|
||||
def is_perfect_square(self):
|
||||
return _gmp.mpz_perfect_square_p(self._mpz_p) != 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")
|
||||
|
||||
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
|
||||
|
||||
def set(self, source):
|
||||
"""Set the Integer to have the given value"""
|
||||
|
||||
if not isinstance(source, IntegerGMP):
|
||||
source = IntegerGMP(source)
|
||||
_gmp.mpz_set(self._mpz_p,
|
||||
source._mpz_p)
|
||||
return self
|
||||
|
||||
def inplace_inverse(self, modulus):
|
||||
"""Compute the inverse of this number in the ring of
|
||||
modulo integers.
|
||||
|
||||
Raise an exception if no inverse exists.
|
||||
"""
|
||||
|
||||
if not isinstance(modulus, IntegerGMP):
|
||||
modulus = IntegerGMP(modulus)
|
||||
|
||||
comp = _gmp.mpz_cmp(modulus._mpz_p,
|
||||
self._zero_mpz_p)
|
||||
if comp == 0:
|
||||
raise ZeroDivisionError("Modulus cannot be zero")
|
||||
if comp < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
|
||||
result = _gmp.mpz_invert(self._mpz_p,
|
||||
self._mpz_p,
|
||||
modulus._mpz_p)
|
||||
if not result:
|
||||
raise ValueError("No inverse value can be computed")
|
||||
return self
|
||||
|
||||
def inverse(self, modulus):
|
||||
result = IntegerGMP(self)
|
||||
result.inplace_inverse(modulus)
|
||||
return result
|
||||
|
||||
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
|
||||
|
||||
def lcm(self, term):
|
||||
"""Compute the least common multiplier between this
|
||||
number and another term."""
|
||||
|
||||
result = IntegerGMP(0)
|
||||
if not isinstance(term, IntegerGMP):
|
||||
term = IntegerGMP(term)
|
||||
_gmp.mpz_lcm(result._mpz_p, self._mpz_p, term._mpz_p)
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def jacobi_symbol(a, n):
|
||||
"""Compute the Jacobi symbol"""
|
||||
|
||||
if not isinstance(a, IntegerGMP):
|
||||
a = IntegerGMP(a)
|
||||
if not isinstance(n, IntegerGMP):
|
||||
n = IntegerGMP(n)
|
||||
if n <= 0 or n.is_even():
|
||||
raise ValueError("n must be positive odd for the Jacobi symbol")
|
||||
return _gmp.mpz_jacobi(a._mpz_p, n._mpz_p)
|
||||
|
||||
@staticmethod
|
||||
def _mult_modulo_bytes(term1, term2, modulus):
|
||||
if not isinstance(term1, IntegerGMP):
|
||||
term1 = IntegerGMP(term1)
|
||||
if not isinstance(term2, IntegerGMP):
|
||||
term2 = IntegerGMP(term2)
|
||||
if not isinstance(modulus, IntegerGMP):
|
||||
modulus = IntegerGMP(modulus)
|
||||
|
||||
if modulus < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
if modulus == 0:
|
||||
raise ZeroDivisionError("Modulus cannot be zero")
|
||||
if (modulus & 1) == 0:
|
||||
raise ValueError("Odd modulus is required")
|
||||
|
||||
product = (term1 * term2) % modulus
|
||||
return product.to_bytes(modulus.size_in_bytes())
|
||||
|
||||
# Clean-up
|
||||
def __del__(self):
|
||||
|
||||
try:
|
||||
if self._mpz_p is not None:
|
||||
if self._initialized:
|
||||
_gmp.mpz_clear(self._mpz_p)
|
||||
|
||||
self._mpz_p = None
|
||||
except AttributeError:
|
||||
pass
|
3
env/lib/python3.12/site-packages/Crypto/Math/_IntegerGMP.pyi
vendored
Normal file
3
env/lib/python3.12/site-packages/Crypto/Math/_IntegerGMP.pyi
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
from ._IntegerBase import IntegerBase
|
||||
class IntegerGMP(IntegerBase):
|
||||
pass
|
382
env/lib/python3.12/site-packages/Crypto/Math/_IntegerNative.py
vendored
Normal file
382
env/lib/python3.12/site-packages/Crypto/Math/_IntegerNative.py
vendored
Normal file
@ -0,0 +1,382 @@
|
||||
# ===================================================================
|
||||
#
|
||||
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
# ===================================================================
|
||||
|
||||
from ._IntegerBase import IntegerBase
|
||||
|
||||
from Crypto.Util.number import long_to_bytes, bytes_to_long, inverse, GCD
|
||||
|
||||
|
||||
class IntegerNative(IntegerBase):
|
||||
"""A class to model a natural integer (including zero)"""
|
||||
|
||||
def __init__(self, value):
|
||||
if isinstance(value, float):
|
||||
raise ValueError("A floating point type is not a natural number")
|
||||
try:
|
||||
self._value = value._value
|
||||
except AttributeError:
|
||||
self._value = value
|
||||
|
||||
# Conversions
|
||||
def __int__(self):
|
||||
return self._value
|
||||
|
||||
def __str__(self):
|
||||
return str(int(self))
|
||||
|
||||
def __repr__(self):
|
||||
return "Integer(%s)" % str(self)
|
||||
|
||||
# Only Python 2.x
|
||||
def __hex__(self):
|
||||
return hex(self._value)
|
||||
|
||||
# Only Python 3.x
|
||||
def __index__(self):
|
||||
return int(self._value)
|
||||
|
||||
def to_bytes(self, block_size=0, byteorder='big'):
|
||||
if self._value < 0:
|
||||
raise ValueError("Conversion only valid for non-negative numbers")
|
||||
result = long_to_bytes(self._value, block_size)
|
||||
if len(result) > block_size > 0:
|
||||
raise ValueError("Value too large to encode")
|
||||
if byteorder == 'big':
|
||||
pass
|
||||
elif byteorder == 'little':
|
||||
result = bytearray(result)
|
||||
result.reverse()
|
||||
result = bytes(result)
|
||||
else:
|
||||
raise ValueError("Incorrect byteorder")
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, byte_string, byteorder='big'):
|
||||
if byteorder == 'big':
|
||||
pass
|
||||
elif byteorder == 'little':
|
||||
byte_string = bytearray(byte_string)
|
||||
byte_string.reverse()
|
||||
else:
|
||||
raise ValueError("Incorrect byteorder")
|
||||
return cls(bytes_to_long(byte_string))
|
||||
|
||||
# Relations
|
||||
def __eq__(self, term):
|
||||
if term is None:
|
||||
return False
|
||||
return self._value == int(term)
|
||||
|
||||
def __ne__(self, term):
|
||||
return not self.__eq__(term)
|
||||
|
||||
def __lt__(self, term):
|
||||
return self._value < int(term)
|
||||
|
||||
def __le__(self, term):
|
||||
return self.__lt__(term) or self.__eq__(term)
|
||||
|
||||
def __gt__(self, term):
|
||||
return not self.__le__(term)
|
||||
|
||||
def __ge__(self, term):
|
||||
return not self.__lt__(term)
|
||||
|
||||
def __nonzero__(self):
|
||||
return self._value != 0
|
||||
__bool__ = __nonzero__
|
||||
|
||||
def is_negative(self):
|
||||
return self._value < 0
|
||||
|
||||
# Arithmetic operations
|
||||
def __add__(self, term):
|
||||
try:
|
||||
return self.__class__(self._value + int(term))
|
||||
except (ValueError, AttributeError, TypeError):
|
||||
return NotImplemented
|
||||
|
||||
def __sub__(self, term):
|
||||
try:
|
||||
return self.__class__(self._value - int(term))
|
||||
except (ValueError, AttributeError, TypeError):
|
||||
return NotImplemented
|
||||
|
||||
def __mul__(self, factor):
|
||||
try:
|
||||
return self.__class__(self._value * int(factor))
|
||||
except (ValueError, AttributeError, TypeError):
|
||||
return NotImplemented
|
||||
|
||||
def __floordiv__(self, divisor):
|
||||
return self.__class__(self._value // int(divisor))
|
||||
|
||||
def __mod__(self, divisor):
|
||||
divisor_value = int(divisor)
|
||||
if divisor_value < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
return self.__class__(self._value % divisor_value)
|
||||
|
||||
def inplace_pow(self, exponent, modulus=None):
|
||||
exp_value = int(exponent)
|
||||
if exp_value < 0:
|
||||
raise ValueError("Exponent must not be negative")
|
||||
|
||||
if modulus is not None:
|
||||
mod_value = int(modulus)
|
||||
if mod_value < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
if mod_value == 0:
|
||||
raise ZeroDivisionError("Modulus cannot be zero")
|
||||
else:
|
||||
mod_value = None
|
||||
self._value = pow(self._value, exp_value, mod_value)
|
||||
return self
|
||||
|
||||
def __pow__(self, exponent, modulus=None):
|
||||
result = self.__class__(self)
|
||||
return result.inplace_pow(exponent, modulus)
|
||||
|
||||
def __abs__(self):
|
||||
return abs(self._value)
|
||||
|
||||
def sqrt(self, modulus=None):
|
||||
|
||||
value = self._value
|
||||
if modulus is None:
|
||||
if value < 0:
|
||||
raise ValueError("Square root of negative value")
|
||||
# http://stackoverflow.com/questions/15390807/integer-square-root-in-python
|
||||
|
||||
x = value
|
||||
y = (x + 1) // 2
|
||||
while y < x:
|
||||
x = y
|
||||
y = (x + value // x) // 2
|
||||
result = x
|
||||
else:
|
||||
if modulus <= 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
result = self._tonelli_shanks(self % modulus, modulus)
|
||||
|
||||
return self.__class__(result)
|
||||
|
||||
def __iadd__(self, term):
|
||||
self._value += int(term)
|
||||
return self
|
||||
|
||||
def __isub__(self, term):
|
||||
self._value -= int(term)
|
||||
return self
|
||||
|
||||
def __imul__(self, term):
|
||||
self._value *= int(term)
|
||||
return self
|
||||
|
||||
def __imod__(self, term):
|
||||
modulus = int(term)
|
||||
if modulus == 0:
|
||||
raise ZeroDivisionError("Division by zero")
|
||||
if modulus < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
self._value %= modulus
|
||||
return self
|
||||
|
||||
# Boolean/bit operations
|
||||
def __and__(self, term):
|
||||
return self.__class__(self._value & int(term))
|
||||
|
||||
def __or__(self, term):
|
||||
return self.__class__(self._value | int(term))
|
||||
|
||||
def __rshift__(self, pos):
|
||||
try:
|
||||
return self.__class__(self._value >> int(pos))
|
||||
except OverflowError:
|
||||
if self._value >= 0:
|
||||
return 0
|
||||
else:
|
||||
return -1
|
||||
|
||||
def __irshift__(self, pos):
|
||||
try:
|
||||
self._value >>= int(pos)
|
||||
except OverflowError:
|
||||
if self._value >= 0:
|
||||
return 0
|
||||
else:
|
||||
return -1
|
||||
return self
|
||||
|
||||
def __lshift__(self, pos):
|
||||
try:
|
||||
return self.__class__(self._value << int(pos))
|
||||
except OverflowError:
|
||||
raise ValueError("Incorrect shift count")
|
||||
|
||||
def __ilshift__(self, pos):
|
||||
try:
|
||||
self._value <<= int(pos)
|
||||
except OverflowError:
|
||||
raise ValueError("Incorrect shift count")
|
||||
return self
|
||||
|
||||
def get_bit(self, n):
|
||||
if self._value < 0:
|
||||
raise ValueError("no bit representation for negative values")
|
||||
try:
|
||||
try:
|
||||
result = (self._value >> n._value) & 1
|
||||
if n._value < 0:
|
||||
raise ValueError("negative bit count")
|
||||
except AttributeError:
|
||||
result = (self._value >> n) & 1
|
||||
if n < 0:
|
||||
raise ValueError("negative bit count")
|
||||
except OverflowError:
|
||||
result = 0
|
||||
return result
|
||||
|
||||
# Extra
|
||||
def is_odd(self):
|
||||
return (self._value & 1) == 1
|
||||
|
||||
def is_even(self):
|
||||
return (self._value & 1) == 0
|
||||
|
||||
def size_in_bits(self):
|
||||
|
||||
if self._value < 0:
|
||||
raise ValueError("Conversion only valid for non-negative numbers")
|
||||
|
||||
if self._value == 0:
|
||||
return 1
|
||||
|
||||
return self._value.bit_length()
|
||||
|
||||
def size_in_bytes(self):
|
||||
return (self.size_in_bits() - 1) // 8 + 1
|
||||
|
||||
def is_perfect_square(self):
|
||||
if self._value < 0:
|
||||
return False
|
||||
if self._value in (0, 1):
|
||||
return True
|
||||
|
||||
x = self._value // 2
|
||||
square_x = x ** 2
|
||||
|
||||
while square_x > self._value:
|
||||
x = (square_x + self._value) // (2 * x)
|
||||
square_x = x ** 2
|
||||
|
||||
return self._value == x ** 2
|
||||
|
||||
def fail_if_divisible_by(self, small_prime):
|
||||
if (self._value % int(small_prime)) == 0:
|
||||
raise ValueError("Value is composite")
|
||||
|
||||
def multiply_accumulate(self, a, b):
|
||||
self._value += int(a) * int(b)
|
||||
return self
|
||||
|
||||
def set(self, source):
|
||||
self._value = int(source)
|
||||
|
||||
def inplace_inverse(self, modulus):
|
||||
self._value = inverse(self._value, int(modulus))
|
||||
return self
|
||||
|
||||
def inverse(self, modulus):
|
||||
result = self.__class__(self)
|
||||
result.inplace_inverse(modulus)
|
||||
return result
|
||||
|
||||
def gcd(self, term):
|
||||
return self.__class__(GCD(abs(self._value), abs(int(term))))
|
||||
|
||||
def lcm(self, term):
|
||||
term = int(term)
|
||||
if self._value == 0 or term == 0:
|
||||
return self.__class__(0)
|
||||
return self.__class__(abs((self._value * term) // self.gcd(term)._value))
|
||||
|
||||
@staticmethod
|
||||
def jacobi_symbol(a, n):
|
||||
a = int(a)
|
||||
n = int(n)
|
||||
|
||||
if n <= 0:
|
||||
raise ValueError("n must be a positive integer")
|
||||
|
||||
if (n & 1) == 0:
|
||||
raise ValueError("n must be odd for the Jacobi symbol")
|
||||
|
||||
# Step 1
|
||||
a = a % n
|
||||
# Step 2
|
||||
if a == 1 or n == 1:
|
||||
return 1
|
||||
# Step 3
|
||||
if a == 0:
|
||||
return 0
|
||||
# Step 4
|
||||
e = 0
|
||||
a1 = a
|
||||
while (a1 & 1) == 0:
|
||||
a1 >>= 1
|
||||
e += 1
|
||||
# Step 5
|
||||
if (e & 1) == 0:
|
||||
s = 1
|
||||
elif n % 8 in (1, 7):
|
||||
s = 1
|
||||
else:
|
||||
s = -1
|
||||
# Step 6
|
||||
if n % 4 == 3 and a1 % 4 == 3:
|
||||
s = -s
|
||||
# Step 7
|
||||
n1 = n % a1
|
||||
# Step 8
|
||||
return s * IntegerNative.jacobi_symbol(n1, a1)
|
||||
|
||||
@staticmethod
|
||||
def _mult_modulo_bytes(term1, term2, modulus):
|
||||
if modulus < 0:
|
||||
raise ValueError("Modulus must be positive")
|
||||
if modulus == 0:
|
||||
raise ZeroDivisionError("Modulus cannot be zero")
|
||||
if (modulus & 1) == 0:
|
||||
raise ValueError("Odd modulus is required")
|
||||
|
||||
number_len = len(long_to_bytes(modulus))
|
||||
return long_to_bytes((term1 * term2) % modulus, number_len)
|
3
env/lib/python3.12/site-packages/Crypto/Math/_IntegerNative.pyi
vendored
Normal file
3
env/lib/python3.12/site-packages/Crypto/Math/_IntegerNative.pyi
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
from ._IntegerBase import IntegerBase
|
||||
class IntegerNative(IntegerBase):
|
||||
pass
|
0
env/lib/python3.12/site-packages/Crypto/Math/__init__.py
vendored
Normal file
0
env/lib/python3.12/site-packages/Crypto/Math/__init__.py
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/Numbers.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/Numbers.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/Primality.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/Primality.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerBase.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerBase.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerCustom.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerCustom.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerGMP.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerGMP.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerNative.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/_IntegerNative.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
BIN
env/lib/python3.12/site-packages/Crypto/Math/__pycache__/__init__.cpython-312.pyc
vendored
Normal file
Binary file not shown.
BIN
env/lib/python3.12/site-packages/Crypto/Math/_modexp.abi3.so
vendored
Executable file
BIN
env/lib/python3.12/site-packages/Crypto/Math/_modexp.abi3.so
vendored
Executable file
Binary file not shown.
Reference in New Issue
Block a user