mirror of
https://gitlab.com/MoonTestUse1/AdministrationItDepartmens.git
synced 2025-08-14 00:25:46 +02:00
Initial commit
This commit is contained in:
184
venv/Lib/site-packages/rsa/common.py
Normal file
184
venv/Lib/site-packages/rsa/common.py
Normal file
@@ -0,0 +1,184 @@
|
||||
# Copyright 2011 Sybren A. Stüvel <sybren@stuvel.eu>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""Common functionality shared by several modules."""
|
||||
|
||||
import typing
|
||||
|
||||
|
||||
class NotRelativePrimeError(ValueError):
|
||||
def __init__(self, a: int, b: int, d: int, msg: str = "") -> None:
|
||||
super().__init__(msg or "%d and %d are not relatively prime, divider=%i" % (a, b, d))
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.d = d
|
||||
|
||||
|
||||
def bit_size(num: int) -> int:
|
||||
"""
|
||||
Number of bits needed to represent a integer excluding any prefix
|
||||
0 bits.
|
||||
|
||||
Usage::
|
||||
|
||||
>>> bit_size(1023)
|
||||
10
|
||||
>>> bit_size(1024)
|
||||
11
|
||||
>>> bit_size(1025)
|
||||
11
|
||||
|
||||
:param num:
|
||||
Integer value. If num is 0, returns 0. Only the absolute value of the
|
||||
number is considered. Therefore, signed integers will be abs(num)
|
||||
before the number's bit length is determined.
|
||||
:returns:
|
||||
Returns the number of bits in the integer.
|
||||
"""
|
||||
|
||||
try:
|
||||
return num.bit_length()
|
||||
except AttributeError as ex:
|
||||
raise TypeError("bit_size(num) only supports integers, not %r" % type(num)) from ex
|
||||
|
||||
|
||||
def byte_size(number: int) -> int:
|
||||
"""
|
||||
Returns the number of bytes required to hold a specific long number.
|
||||
|
||||
The number of bytes is rounded up.
|
||||
|
||||
Usage::
|
||||
|
||||
>>> byte_size(1 << 1023)
|
||||
128
|
||||
>>> byte_size((1 << 1024) - 1)
|
||||
128
|
||||
>>> byte_size(1 << 1024)
|
||||
129
|
||||
|
||||
:param number:
|
||||
An unsigned integer
|
||||
:returns:
|
||||
The number of bytes required to hold a specific long number.
|
||||
"""
|
||||
if number == 0:
|
||||
return 1
|
||||
return ceil_div(bit_size(number), 8)
|
||||
|
||||
|
||||
def ceil_div(num: int, div: int) -> int:
|
||||
"""
|
||||
Returns the ceiling function of a division between `num` and `div`.
|
||||
|
||||
Usage::
|
||||
|
||||
>>> ceil_div(100, 7)
|
||||
15
|
||||
>>> ceil_div(100, 10)
|
||||
10
|
||||
>>> ceil_div(1, 4)
|
||||
1
|
||||
|
||||
:param num: Division's numerator, a number
|
||||
:param div: Division's divisor, a number
|
||||
|
||||
:return: Rounded up result of the division between the parameters.
|
||||
"""
|
||||
quanta, mod = divmod(num, div)
|
||||
if mod:
|
||||
quanta += 1
|
||||
return quanta
|
||||
|
||||
|
||||
def extended_gcd(a: int, b: int) -> typing.Tuple[int, int, int]:
|
||||
"""Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb"""
|
||||
# r = gcd(a,b) i = multiplicitive inverse of a mod b
|
||||
# or j = multiplicitive inverse of b mod a
|
||||
# Neg return values for i or j are made positive mod b or a respectively
|
||||
# Iterateive Version is faster and uses much less stack space
|
||||
x = 0
|
||||
y = 1
|
||||
lx = 1
|
||||
ly = 0
|
||||
oa = a # Remember original a/b to remove
|
||||
ob = b # negative values from return results
|
||||
while b != 0:
|
||||
q = a // b
|
||||
(a, b) = (b, a % b)
|
||||
(x, lx) = ((lx - (q * x)), x)
|
||||
(y, ly) = ((ly - (q * y)), y)
|
||||
if lx < 0:
|
||||
lx += ob # If neg wrap modulo original b
|
||||
if ly < 0:
|
||||
ly += oa # If neg wrap modulo original a
|
||||
return a, lx, ly # Return only positive values
|
||||
|
||||
|
||||
def inverse(x: int, n: int) -> int:
|
||||
"""Returns the inverse of x % n under multiplication, a.k.a x^-1 (mod n)
|
||||
|
||||
>>> inverse(7, 4)
|
||||
3
|
||||
>>> (inverse(143, 4) * 143) % 4
|
||||
1
|
||||
"""
|
||||
|
||||
(divider, inv, _) = extended_gcd(x, n)
|
||||
|
||||
if divider != 1:
|
||||
raise NotRelativePrimeError(x, n, divider)
|
||||
|
||||
return inv
|
||||
|
||||
|
||||
def crt(a_values: typing.Iterable[int], modulo_values: typing.Iterable[int]) -> int:
|
||||
"""Chinese Remainder Theorem.
|
||||
|
||||
Calculates x such that x = a[i] (mod m[i]) for each i.
|
||||
|
||||
:param a_values: the a-values of the above equation
|
||||
:param modulo_values: the m-values of the above equation
|
||||
:returns: x such that x = a[i] (mod m[i]) for each i
|
||||
|
||||
|
||||
>>> crt([2, 3], [3, 5])
|
||||
8
|
||||
|
||||
>>> crt([2, 3, 2], [3, 5, 7])
|
||||
23
|
||||
|
||||
>>> crt([2, 3, 0], [7, 11, 15])
|
||||
135
|
||||
"""
|
||||
|
||||
m = 1
|
||||
x = 0
|
||||
|
||||
for modulo in modulo_values:
|
||||
m *= modulo
|
||||
|
||||
for (m_i, a_i) in zip(modulo_values, a_values):
|
||||
M_i = m // m_i
|
||||
inv = inverse(M_i, m_i)
|
||||
|
||||
x = (x + a_i * M_i * inv) % m
|
||||
|
||||
return x
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
Reference in New Issue
Block a user