kryptools 0.9.4__tar.gz → 0.9.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kryptools-0.9.4 → kryptools-0.9.5}/PKG-INFO +1 -1
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/poly.py +19 -4
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/primes.py +69 -11
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/PKG-INFO +1 -1
- {kryptools-0.9.4 → kryptools-0.9.5}/pyproject.toml +1 -1
- {kryptools-0.9.4 → kryptools-0.9.5}/LICENSE +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/README.md +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/Zmod.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/__init__.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_ic.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_qs.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_rho.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/ec.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_dix.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_ecm.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_fmt.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_pm1.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_qs.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/la.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/lat.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/nt.py +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/SOURCES.txt +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-0.9.4 → kryptools-0.9.5}/setup.cfg +0 -0
|
@@ -4,6 +4,14 @@ Polynomials
|
|
|
4
4
|
|
|
5
5
|
from numbers import Number
|
|
6
6
|
|
|
7
|
+
display_reversed = True
|
|
8
|
+
|
|
9
|
+
def poly_style_reversed(value: bool = True) -> None:
|
|
10
|
+
"Change the order of the coefficients when displaying polynomials."
|
|
11
|
+
global display_reversed
|
|
12
|
+
display_reversed = value
|
|
13
|
+
|
|
14
|
+
|
|
7
15
|
class Poly:
|
|
8
16
|
"""
|
|
9
17
|
Represents a polynomial as a list of coefficients.
|
|
@@ -40,7 +48,7 @@ class Poly:
|
|
|
40
48
|
return len(self.coeff)
|
|
41
49
|
|
|
42
50
|
def __repr__(self):
|
|
43
|
-
def prx(i: int):
|
|
51
|
+
def prx(i: int) -> str:
|
|
44
52
|
if i == 0:
|
|
45
53
|
return ""
|
|
46
54
|
if i == 1:
|
|
@@ -51,7 +59,10 @@ class Poly:
|
|
|
51
59
|
return str(self.coeff[0])
|
|
52
60
|
plus = ""
|
|
53
61
|
tmp = ""
|
|
54
|
-
|
|
62
|
+
coef_range = range(len(self.coeff))
|
|
63
|
+
if display_reversed:
|
|
64
|
+
coef_range = reversed(coef_range)
|
|
65
|
+
for i in coef_range:
|
|
55
66
|
s = self.coeff[i]
|
|
56
67
|
if not s:
|
|
57
68
|
continue
|
|
@@ -70,11 +81,15 @@ class Poly:
|
|
|
70
81
|
pass
|
|
71
82
|
try:
|
|
72
83
|
if plus and s < 0:
|
|
73
|
-
tmp += " - " + str(-s)
|
|
84
|
+
tmp += " - " + str(-s)
|
|
85
|
+
if i != 0:
|
|
86
|
+
tmp += " " + prx(i)
|
|
74
87
|
continue
|
|
75
88
|
except:
|
|
76
89
|
pass
|
|
77
|
-
tmp += plus + str(s)
|
|
90
|
+
tmp += plus + str(s)
|
|
91
|
+
if i != 0:
|
|
92
|
+
tmp += " " + prx(i)
|
|
78
93
|
plus = " + "
|
|
79
94
|
return tmp.strip()
|
|
80
95
|
|
|
@@ -13,6 +13,9 @@ Tools for prime numbers:
|
|
|
13
13
|
random_blumprime(l) find a pseudorandom Blum prime with bit length at least l
|
|
14
14
|
miller_rabin_test(n, b) Miller-Rabin primality test with base b
|
|
15
15
|
lucas_test(n) strong Lucas test
|
|
16
|
+
perfect_square(n) test if a number is a perfect square
|
|
17
|
+
perfect_power(n) test if a number is a perfect power
|
|
18
|
+
iroot(k, n) integer k'th root of n
|
|
16
19
|
"""
|
|
17
20
|
from math import isqrt, gcd, floor, ceil
|
|
18
21
|
from random import randint
|
|
@@ -51,26 +54,37 @@ def miller_rabin_test(n: int, bases: list[int] | int) -> bool:
|
|
|
51
54
|
"""Run a Miller-Rabin test with given bases on `n`."""
|
|
52
55
|
if n < 2:
|
|
53
56
|
return False
|
|
54
|
-
if n % 2 == 0:
|
|
57
|
+
if n % 2 == 0: # make sure n is odd
|
|
55
58
|
return n == 2
|
|
59
|
+
|
|
60
|
+
# write n = m 2^k + 1
|
|
56
61
|
m = (n - 1) // 2
|
|
57
62
|
k = 1
|
|
58
63
|
while m % 2 == 0:
|
|
59
64
|
m //= 2
|
|
60
65
|
k += 1
|
|
66
|
+
|
|
61
67
|
if isinstance(bases, int):
|
|
62
68
|
bases = [bases]
|
|
69
|
+
|
|
63
70
|
for a in bases:
|
|
71
|
+
a %= n
|
|
72
|
+
if a == 0:
|
|
73
|
+
continue
|
|
64
74
|
b = pow(a, m, n)
|
|
65
75
|
if b == 1 or b == n - 1:
|
|
66
|
-
|
|
76
|
+
continue
|
|
67
77
|
for _ in range(1, k):
|
|
68
78
|
b = pow(b, 2, n)
|
|
69
|
-
if b ==
|
|
79
|
+
if b == 0: # n and a are not coprime
|
|
80
|
+
return False
|
|
81
|
+
if b == 1: # 1 before -1
|
|
70
82
|
return False
|
|
71
83
|
if b == n - 1:
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
break
|
|
85
|
+
else: # no -1 found
|
|
86
|
+
return False
|
|
87
|
+
return True
|
|
74
88
|
|
|
75
89
|
def _lucas_sequence(n, D, k):
|
|
76
90
|
"""Evaluate a Lucas sequence."""
|
|
@@ -97,16 +111,56 @@ def _lucas_sequence(n, D, k):
|
|
|
97
111
|
return U % n, V % n, Qk
|
|
98
112
|
|
|
99
113
|
|
|
114
|
+
def perfect_square(n: int) -> int|None:
|
|
115
|
+
"""Returns the root if `n` is a perfect square and None else."""
|
|
116
|
+
s = isqrt(n)
|
|
117
|
+
if s*s == n:
|
|
118
|
+
return s
|
|
119
|
+
|
|
120
|
+
def iroot(k: int, n: int) -> int:
|
|
121
|
+
"""Compute the integer k'th root of n."""
|
|
122
|
+
if not isinstance(k, int) or n < 1:
|
|
123
|
+
raise ValueError(f"{k} is not a positive integer")
|
|
124
|
+
if k == 1:
|
|
125
|
+
return n
|
|
126
|
+
if k == 2:
|
|
127
|
+
return isqrt(n)
|
|
128
|
+
rr = isqrt(n)
|
|
129
|
+
r =rr + 1
|
|
130
|
+
k1 = k-1
|
|
131
|
+
while rr < r:
|
|
132
|
+
r = rr
|
|
133
|
+
rr = (k1 * r + n // r ** k1) // k # Newton iteration
|
|
134
|
+
return r
|
|
135
|
+
|
|
136
|
+
def perfect_power(n: int) -> tuple|None:
|
|
137
|
+
"""Returns integers `(m, p)` with `m**p == n` if `n` is a perfect power and None else."""
|
|
138
|
+
for p in sieve_eratosthenes(n.bit_length() - 1):
|
|
139
|
+
m = iroot(p, n)
|
|
140
|
+
if pow(m, p) == n:
|
|
141
|
+
return (m, p)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# https://en.wikipedia.org/wiki/Lucas_pseudoprime#Implementing_a_Lucas_probable_prime_test
|
|
145
|
+
|
|
100
146
|
def lucas_test(n: int) -> bool:
|
|
101
147
|
"""Run a strong Lucas primality test on `n`."""
|
|
102
|
-
|
|
103
|
-
|
|
148
|
+
if n < 2:
|
|
149
|
+
return False
|
|
150
|
+
if n % 2 == 0:
|
|
151
|
+
return n == 2
|
|
152
|
+
if perfect_square(n) is not None: # the search for D will not succeed in this case
|
|
153
|
+
return False
|
|
154
|
+
|
|
155
|
+
# write n = k 2^s - 1
|
|
104
156
|
k = (n + 1) // 2
|
|
105
157
|
s = 1
|
|
106
158
|
while k % 2 == 0:
|
|
107
159
|
k //= 2
|
|
108
160
|
s += 1
|
|
109
|
-
|
|
161
|
+
|
|
162
|
+
# Selfridge method for choosing D
|
|
163
|
+
|
|
110
164
|
D = 5
|
|
111
165
|
while True:
|
|
112
166
|
g = gcd(abs(D), n)
|
|
@@ -119,9 +173,6 @@ def lucas_test(n: int) -> bool:
|
|
|
119
173
|
else:
|
|
120
174
|
D = -D + 2
|
|
121
175
|
|
|
122
|
-
if D == 0:
|
|
123
|
-
return False
|
|
124
|
-
|
|
125
176
|
U, V, Qk = _lucas_sequence(n, D, k)
|
|
126
177
|
|
|
127
178
|
if U == 0 or V == 0:
|
|
@@ -135,6 +186,13 @@ def lucas_test(n: int) -> bool:
|
|
|
135
186
|
|
|
136
187
|
def is_prime(n: int) -> bool:
|
|
137
188
|
"""Test if an integer `n` if probable prime."""
|
|
189
|
+
# Test small primes
|
|
190
|
+
for p in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
|
|
191
|
+
101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199,
|
|
192
|
+
211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293,
|
|
193
|
+
307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397):
|
|
194
|
+
if n % p == 0:
|
|
195
|
+
return n == p
|
|
138
196
|
if n < 18446744073709551616: # https://miller-rabin.appspot.com
|
|
139
197
|
return miller_rabin_test(n, [2, 325, 9375, 28178, 450775, 9780504, 1795265022])
|
|
140
198
|
if n < 3317044064679887385961981:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|