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.
Files changed (29) hide show
  1. {kryptools-0.9.6 → kryptools-0.9.7}/PKG-INFO +1 -1
  2. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor.py +10 -3
  3. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_dix.py +2 -2
  4. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_ecm.py +11 -7
  5. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_pm1.py +14 -8
  6. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_qs.py +1 -1
  7. kryptools-0.9.7/kryptools/factor_rho.py +58 -0
  8. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/PKG-INFO +1 -1
  9. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/SOURCES.txt +1 -0
  10. {kryptools-0.9.6 → kryptools-0.9.7}/pyproject.toml +1 -1
  11. {kryptools-0.9.6 → kryptools-0.9.7}/LICENSE +0 -0
  12. {kryptools-0.9.6 → kryptools-0.9.7}/README.md +0 -0
  13. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/Zmod.py +0 -0
  14. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/__init__.py +0 -0
  15. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp.py +0 -0
  16. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_bsgs.py +0 -0
  17. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_ic.py +0 -0
  18. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_qs.py +0 -0
  19. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/dlp_rho.py +0 -0
  20. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/ec.py +0 -0
  21. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/factor_fmt.py +0 -0
  22. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/la.py +0 -0
  23. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/lat.py +0 -0
  24. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/nt.py +0 -0
  25. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/poly.py +0 -0
  26. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools/primes.py +0 -0
  27. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/dependency_links.txt +0 -0
  28. {kryptools-0.9.6 → kryptools-0.9.7}/kryptools.egg-info/top_level.txt +0 -0
  29. {kryptools-0.9.6 → kryptools-0.9.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kryptools
3
- Version: 0.9.6
3
+ Version: 0.9.7
4
4
  Summary: Implemenation of same basic algorithms used in cryptography.
5
5
  Author-email: Gerald Teschl <gerald.teschl@univie.ac.at>
6
6
  Project-URL: Homepage, https://github.com/teschlg/kryptools
@@ -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 or None:
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) -> list:
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
- B1 += B1 & 1
56
+ if B1 % 2:
57
+ raise ValueError("B1 must be even.")
57
58
  if not B2:
58
59
  B2 = 100 * B1
59
- else:
60
- B2 += B2 & 1
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 = max(2, isqrt(n//200))
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 = 10000, B2: int|None = None, x: int = 2, pm1_parameters: tuple = None, verbose: int = 0):
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) -> list:
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
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kryptools
3
- Version: 0.9.6
3
+ Version: 0.9.7
4
4
  Summary: Implemenation of same basic algorithms used in cryptography.
5
5
  Author-email: Gerald Teschl <gerald.teschl@univie.ac.at>
6
6
  Project-URL: Homepage, https://github.com/teschlg/kryptools
@@ -15,6 +15,7 @@ kryptools/factor_ecm.py
15
15
  kryptools/factor_fmt.py
16
16
  kryptools/factor_pm1.py
17
17
  kryptools/factor_qs.py
18
+ kryptools/factor_rho.py
18
19
  kryptools/la.py
19
20
  kryptools/lat.py
20
21
  kryptools/nt.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "0.9.6"
3
+ version = "0.9.7"
4
4
  authors = [
5
5
  { name="Gerald Teschl", email="gerald.teschl@univie.ac.at" },
6
6
  ]
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