kryptools 0.9.6__tar.gz → 0.9.7__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.6 → kryptools-0.9.7}/PKG-INFO +1 -1
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor.py +10 -3
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_dix.py +2 -2
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_ecm.py +11 -7
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_pm1.py +14 -8
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_qs.py +1 -1
- kryptools-0.9.7/kryptools/factor_rho.py +58 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/PKG-INFO +1 -1
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/SOURCES.txt +1 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/pyproject.toml +1 -1
- {kryptools-0.9.6 → kryptools-0.9.7}/LICENSE +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/README.md +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/Zmod.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/__init__.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_ic.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_qs.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_rho.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/ec.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_fmt.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/la.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/lat.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/nt.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/poly.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/primes.py +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-0.9.6 → kryptools-0.9.7}/setup.cfg +0 -0
|
@@ -107,14 +107,21 @@ def factorint(n: int, verbose: int = 0, trial_bnd: int = 2500) -> dict:
|
|
|
107
107
|
fermat_steps = 10
|
|
108
108
|
|
|
109
109
|
for round, parameters in enumerate(ECM_PARAMETERS):
|
|
110
|
-
if verbose:
|
|
111
|
-
print(f"Round {round+1}")
|
|
112
110
|
fermat_steps += 10
|
|
113
111
|
B1, B2, num_curves = parameters
|
|
112
|
+
p_max = isqrt(max(remaining_factors))+1
|
|
113
|
+
B1 = min(B1, p_max//50)
|
|
114
|
+
B1 += B1 & 1
|
|
115
|
+
B2 = min(B2, p_max)
|
|
116
|
+
B2 += B2 & 1
|
|
114
117
|
num_curves *= 2
|
|
115
118
|
D = isqrt(B2)
|
|
119
|
+
|
|
120
|
+
if verbose:
|
|
121
|
+
print(f"Round {round+1} (B1={B1})")
|
|
122
|
+
|
|
116
123
|
primes = sieve_eratosthenes(B1 - 1 + ((B2 - B1 + 1) // (2 * D) + 1) * 2 * D)
|
|
117
|
-
pm1_parameters = _pm1_parameters(10 * B1, B2, primes = primes)
|
|
124
|
+
pm1_parameters = tuple([10 * B1, B2] + list(_pm1_parameters(10 * B1, B2, primes = primes)))
|
|
118
125
|
ecm_parameters = tuple([B1, B2, num_curves] + list(_ecm_parameters(B1, B2, D, primes = primes)))
|
|
119
126
|
|
|
120
127
|
methods = {_factor_fermat: "fmt", factor_pm1: "pm1", factor_ecm: "ecm"} #, factor_qs: "qs"}
|
|
@@ -7,7 +7,7 @@ from .primes import sieve_eratosthenes
|
|
|
7
7
|
from .nt import legendre_symbol
|
|
8
8
|
from .factor_qs import bytexor, byteset, bytetest
|
|
9
9
|
|
|
10
|
-
def is_smooth(n: int, factorbase: list, lfb: int) -> bytes
|
|
10
|
+
def is_smooth(n: int, factorbase: list, lfb: int) -> bytes|None:
|
|
11
11
|
"""Try to factor n with respect to a given factorbase.
|
|
12
12
|
Upon success a bytestring, whose bits are the exponents with repect to the factorbase mod 2, is returned.
|
|
13
13
|
Otherwise None."""
|
|
@@ -26,7 +26,7 @@ def is_smooth(n: int, factorbase: list, lfb: int) -> bytes or None:
|
|
|
26
26
|
return None # the number factors if at the end nothing is left
|
|
27
27
|
return factors
|
|
28
28
|
|
|
29
|
-
def factor_dixon(n: int) ->
|
|
29
|
+
def factor_dixon(n: int) -> int|None:
|
|
30
30
|
"""Find factors of n using the method of Dixon."""
|
|
31
31
|
# first determine the bound B for the factorbase: Choosing B=p^(1/u) Canfield-Erdös-Pomerance gives us
|
|
32
32
|
# the expected running time |B|^2 u^u = u^(u+2) p^(2/u)/log(n). There is no explicit expression for the optimum, hence
|
|
@@ -49,15 +49,16 @@ def mult(k, P, c2, p):
|
|
|
49
49
|
# Crandall and Pomerance: Primes (doi=10.1007/0-387-28979-8)
|
|
50
50
|
# Algorithm 7.4.4 (Inversionless ECM)
|
|
51
51
|
|
|
52
|
-
def _ecm_parameters(B1: int, B2: int|None = None, D: int|None = None, primes: tuple|None = None):
|
|
52
|
+
def _ecm_parameters(B1: int, B2: int|None = None, D: int|None = None, primes: tuple|None = None) -> tuple:
|
|
53
53
|
"Precompute parameters for the ECM method."
|
|
54
54
|
|
|
55
55
|
# Stage-one/two limits must be even
|
|
56
|
-
|
|
56
|
+
if B1 % 2:
|
|
57
|
+
raise ValueError("B1 must be even.")
|
|
57
58
|
if not B2:
|
|
58
59
|
B2 = 100 * B1
|
|
59
|
-
|
|
60
|
-
B2
|
|
60
|
+
if B2 % 2:
|
|
61
|
+
raise ValueError("B2 must be even.")
|
|
61
62
|
if not D:
|
|
62
63
|
D = min(isqrt(B2), B1 // 2 - 1)
|
|
63
64
|
if not primes:
|
|
@@ -86,14 +87,16 @@ def _ecm_parameters(B1: int, B2: int|None = None, D: int|None = None, primes: tu
|
|
|
86
87
|
return D, stage_one, stage_two_deltas
|
|
87
88
|
|
|
88
89
|
|
|
89
|
-
def factor_ecm(n: int, B1: int|None = None, B2: int|None = None, curves: int = 150, ecm_parameters: tuple|None = None, verbose: int = 0):
|
|
90
|
+
def factor_ecm(n: int, B1: int|None = None, B2: int|None = None, curves: int = 150, ecm_parameters: tuple|None = None, verbose: int = 0) -> int|None:
|
|
90
91
|
"Factors a number n using Lentsta's ECM method."
|
|
91
92
|
|
|
92
93
|
if ecm_parameters:
|
|
93
94
|
B1, B2, curves, D, stage_one, stage_two_deltas = ecm_parameters
|
|
94
95
|
else:
|
|
95
96
|
if not B1:
|
|
96
|
-
B1 =
|
|
97
|
+
B1 = min(1000_000, isqrt(n)//200 + 2)
|
|
98
|
+
# Stage-one/two limits must be even
|
|
99
|
+
B1 += B1 & 1
|
|
97
100
|
if not B2:
|
|
98
101
|
B2 = 100 * B1
|
|
99
102
|
D, stage_one, stage_two_deltas = _ecm_parameters(B1, B2)
|
|
@@ -159,7 +162,7 @@ def factor_ecm(n: int, B1: int|None = None, B2: int|None = None, curves: int = 1
|
|
|
159
162
|
break
|
|
160
163
|
if g == 0:
|
|
161
164
|
break
|
|
162
|
-
g =gcd(g,n)
|
|
165
|
+
g = gcd(g,n)
|
|
163
166
|
if 1 < g:
|
|
164
167
|
if verbose > 1:
|
|
165
168
|
print("\nFactor found.")
|
|
@@ -171,6 +174,7 @@ def factor_ecm(n: int, B1: int|None = None, B2: int|None = None, curves: int = 1
|
|
|
171
174
|
if verbose > 1:
|
|
172
175
|
print("\nFactor found.")
|
|
173
176
|
return g
|
|
177
|
+
|
|
174
178
|
if verbose > 1:
|
|
175
179
|
print(f"\nNo factor after trying {curves} curves.")
|
|
176
180
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Integer factorization: Pollard's p-1 method
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from math import gcd, log, floor, log10
|
|
5
|
+
from math import gcd, log, isqrt, floor, log10
|
|
6
6
|
from .primes import sieve_eratosthenes
|
|
7
7
|
|
|
8
|
-
def _pm1_parameters(B1: int, B2: int|None = None, primes: tuple = None):
|
|
8
|
+
def _pm1_parameters(B1: int, B2: int|None = None, primes: tuple = None) -> tuple:
|
|
9
9
|
"Precompute parameters for the p-1 method."
|
|
10
10
|
if not B2:
|
|
11
11
|
B2 = 100 * B1
|
|
@@ -27,24 +27,30 @@ def _pm1_parameters(B1: int, B2: int|None = None, primes: tuple = None):
|
|
|
27
27
|
return stage_one, stage_two_deltas
|
|
28
28
|
|
|
29
29
|
|
|
30
|
-
def factor_pm1(n: int, B1: int =
|
|
31
|
-
"Factors a number n using Pollard's p-1 method."
|
|
32
|
-
if verbose:
|
|
33
|
-
print(f"Factoring (Pollard p-1, B1={B1}, B2={B2}): {n} ({floor(log10(n)) + 1} digits)")
|
|
34
|
-
|
|
30
|
+
def factor_pm1(n: int, B1: int|None = None, B2: int|None = None, x: int = 2, pm1_parameters: tuple = None, verbose: int = 0) -> int|None:
|
|
31
|
+
"Factors a number n using Pollard's p-1 method."
|
|
35
32
|
if pm1_parameters:
|
|
36
|
-
stage_one, stage_two_deltas = pm1_parameters
|
|
33
|
+
B1, B2, stage_one, stage_two_deltas = pm1_parameters
|
|
37
34
|
else:
|
|
35
|
+
if not B1:
|
|
36
|
+
B1 = min(1000_000, isqrt(n)//50 + 2)
|
|
38
37
|
stage_one, stage_two_deltas = _pm1_parameters(B1, B2)
|
|
39
38
|
|
|
39
|
+
if verbose:
|
|
40
|
+
print(f"Factoring (Pollard p-1, B1={B1}, B2={B2}): {n} ({floor(log10(n)) + 1} digits)")
|
|
41
|
+
|
|
40
42
|
# stage one
|
|
41
43
|
if verbose > 1:
|
|
42
44
|
print("Working 1", end= "")
|
|
43
45
|
x = pow(x, stage_one, n)
|
|
44
46
|
g = gcd(x - 1, n)
|
|
45
47
|
if g == n:
|
|
48
|
+
if verbose > 1:
|
|
49
|
+
print("")
|
|
46
50
|
return None
|
|
47
51
|
if 1 < g:
|
|
52
|
+
if verbose > 1:
|
|
53
|
+
print("\nFactor found.")
|
|
48
54
|
return g
|
|
49
55
|
|
|
50
56
|
if verbose > 1:
|
|
@@ -24,7 +24,7 @@ def bytetest(a: bytes, i: int) -> bytes:
|
|
|
24
24
|
return (a[i1] & 2**i0) != 0
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
def factor_qs(n: int, verbose: int = 0) ->
|
|
27
|
+
def factor_qs(n: int, verbose: int = 0) -> int|None:
|
|
28
28
|
"""Find factors of n using the quadratic sieve."""
|
|
29
29
|
# first determine the bound B for the factorbase: Choosing B=p^(1/u) Canfield-Erdös-Pomerance gives us
|
|
30
30
|
# the expected running time |B|^2 u^u = u^(u+2) p^(2/u)/log(n). There is no explicit expression for the optimum, hence
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integer factorization: Pollard's rho method
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from math import gcd, isqrt, floor, log10
|
|
6
|
+
from random import randint
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def factor_rho(n: int, x: int = 2, maxinit: int = 10, maxiter: int = 1000, brent: bool = True, verbose: int = 0) -> int|None:
|
|
10
|
+
"""Factor n using the Pollard's rho method with start value x."""
|
|
11
|
+
if not maxiter:
|
|
12
|
+
maxiter = 10 * isqrt(n) # stop iterating and try a different start value
|
|
13
|
+
|
|
14
|
+
def f(x: int) -> int:
|
|
15
|
+
return (pow(x, 2, n) + 2) % n
|
|
16
|
+
|
|
17
|
+
if verbose:
|
|
18
|
+
print(f"Factoring (Pollard rho, maxinit={maxinit}, maxiter={maxiter}): {n} ({floor(log10(n)) + 1} digits)")
|
|
19
|
+
|
|
20
|
+
if verbose > 1:
|
|
21
|
+
print("Working ", end= "")
|
|
22
|
+
for _ in range(maxinit):
|
|
23
|
+
if verbose > 1:
|
|
24
|
+
print("X", end= "")
|
|
25
|
+
if not brent: # Floyd's cycle detection algorithm
|
|
26
|
+
i = 1
|
|
27
|
+
x = f(x) # x_1=f(x_0)
|
|
28
|
+
y = f(x) # y_1=f(f(x_0))
|
|
29
|
+
while gcd(x - y, n) == 1 and i < maxiter:
|
|
30
|
+
if verbose > 1 and i % 100 == 0:
|
|
31
|
+
print(".", end= "")
|
|
32
|
+
i += 1
|
|
33
|
+
x = f(x) # f(x_j)
|
|
34
|
+
y = f(y)
|
|
35
|
+
y = f(y) # f(f(y_j))
|
|
36
|
+
else: # Brent's cycle detection algorithm
|
|
37
|
+
i = 1 # search for a cycle length k < 2^i
|
|
38
|
+
k = 1 # cycle length
|
|
39
|
+
y = f(x) # f(x_0)
|
|
40
|
+
while gcd(x - y, n) == 1 and i < maxiter:
|
|
41
|
+
if verbose > 1 and (i+k) % 100 == 0:
|
|
42
|
+
print(".", end= "")
|
|
43
|
+
if i == k: # start a new power of 2
|
|
44
|
+
x = y
|
|
45
|
+
i *= 2
|
|
46
|
+
k = 0
|
|
47
|
+
y = f(y)
|
|
48
|
+
k += 1
|
|
49
|
+
# we found a collission (or hit max)
|
|
50
|
+
tmp = gcd(x - y, n)
|
|
51
|
+
if 1 < tmp < n:
|
|
52
|
+
if verbose > 1:
|
|
53
|
+
print("\nFactor found.")
|
|
54
|
+
return tmp
|
|
55
|
+
x = randint(1, n - 1) # new x_0
|
|
56
|
+
if verbose > 1:
|
|
57
|
+
print("")
|
|
58
|
+
|
|
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
|