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.
Files changed (28) hide show
  1. {kryptools-0.9.4 → kryptools-0.9.5}/PKG-INFO +1 -1
  2. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/poly.py +19 -4
  3. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/primes.py +69 -11
  4. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/PKG-INFO +1 -1
  5. {kryptools-0.9.4 → kryptools-0.9.5}/pyproject.toml +1 -1
  6. {kryptools-0.9.4 → kryptools-0.9.5}/LICENSE +0 -0
  7. {kryptools-0.9.4 → kryptools-0.9.5}/README.md +0 -0
  8. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/Zmod.py +0 -0
  9. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/__init__.py +0 -0
  10. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp.py +0 -0
  11. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_bsgs.py +0 -0
  12. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_ic.py +0 -0
  13. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_qs.py +0 -0
  14. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/dlp_rho.py +0 -0
  15. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/ec.py +0 -0
  16. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor.py +0 -0
  17. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_dix.py +0 -0
  18. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_ecm.py +0 -0
  19. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_fmt.py +0 -0
  20. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_pm1.py +0 -0
  21. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/factor_qs.py +0 -0
  22. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/la.py +0 -0
  23. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/lat.py +0 -0
  24. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools/nt.py +0 -0
  25. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/SOURCES.txt +0 -0
  26. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/dependency_links.txt +0 -0
  27. {kryptools-0.9.4 → kryptools-0.9.5}/kryptools.egg-info/top_level.txt +0 -0
  28. {kryptools-0.9.4 → kryptools-0.9.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kryptools
3
- Version: 0.9.4
3
+ Version: 0.9.5
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
@@ -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
- for i in reversed(range(len(self.coeff))):
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) + " " + prx(i)
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) + " " + prx(i)
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
- return True
76
+ continue
67
77
  for _ in range(1, k):
68
78
  b = pow(b, 2, n)
69
- if b == 1:
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
- return True
73
- return False
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
- # remove powers of 2 from n+1 (= k * 2**s)
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
- # gernerate parameters
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:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kryptools
3
- Version: 0.9.4
3
+ Version: 0.9.5
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "0.9.4"
3
+ version = "0.9.5"
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