kryptools 0.5__tar.gz → 0.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 (28) hide show
  1. {kryptools-0.5 → kryptools-0.7}/PKG-INFO +1 -1
  2. {kryptools-0.5 → kryptools-0.7}/kryptools/Zmod.py +6 -0
  3. {kryptools-0.5 → kryptools-0.7}/kryptools/__init__.py +1 -1
  4. {kryptools-0.5 → kryptools-0.7}/kryptools/la.py +16 -4
  5. {kryptools-0.5 → kryptools-0.7}/kryptools/lat.py +13 -4
  6. {kryptools-0.5 → kryptools-0.7}/kryptools/poly.py +46 -14
  7. {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/PKG-INFO +1 -1
  8. {kryptools-0.5 → kryptools-0.7}/pyproject.toml +1 -1
  9. {kryptools-0.5 → kryptools-0.7}/LICENSE +0 -0
  10. {kryptools-0.5 → kryptools-0.7}/README.md +0 -0
  11. {kryptools-0.5 → kryptools-0.7}/kryptools/dlp.py +0 -0
  12. {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_bsgs.py +0 -0
  13. {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_ic.py +0 -0
  14. {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_qs.py +0 -0
  15. {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_rho.py +0 -0
  16. {kryptools-0.5 → kryptools-0.7}/kryptools/ec.py +0 -0
  17. {kryptools-0.5 → kryptools-0.7}/kryptools/factor.py +0 -0
  18. {kryptools-0.5 → kryptools-0.7}/kryptools/factor_dix.py +0 -0
  19. {kryptools-0.5 → kryptools-0.7}/kryptools/factor_ecm.py +0 -0
  20. {kryptools-0.5 → kryptools-0.7}/kryptools/factor_fmt.py +0 -0
  21. {kryptools-0.5 → kryptools-0.7}/kryptools/factor_pm1.py +0 -0
  22. {kryptools-0.5 → kryptools-0.7}/kryptools/factor_qs.py +0 -0
  23. {kryptools-0.5 → kryptools-0.7}/kryptools/nt.py +0 -0
  24. {kryptools-0.5 → kryptools-0.7}/kryptools/primes.py +0 -0
  25. {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/SOURCES.txt +0 -0
  26. {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/dependency_links.txt +0 -0
  27. {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/top_level.txt +0 -0
  28. {kryptools-0.5 → kryptools-0.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kryptools
3
- Version: 0.5
3
+ Version: 0.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
@@ -106,6 +106,9 @@ class ZmodPoint:
106
106
  def __neg__(self) -> "ZmodPoint":
107
107
  return self.__class__(-self.x, self.ring)
108
108
 
109
+ def __pos__(self) -> "ZmodPoint":
110
+ return self
111
+
109
112
  def __sub__(self, other: "ZmodPoint") -> "ZmodPoint":
110
113
  if isinstance(other, self.__class__):
111
114
  if self.ring != other.ring:
@@ -151,6 +154,9 @@ class ZmodPoint:
151
154
  return self.__class__(pow(self.x, scalar, self.ring.n), self.ring)
152
155
  return NotImplemented
153
156
 
157
+ def __abs__(self) -> int:
158
+ return abs(self.sharp())
159
+
154
160
  def sharp(self):
155
161
  "Returns a symmetric (w.r.t. 0) representative."
156
162
  tmp = (self.ring.n - 1) // 2
@@ -8,6 +8,6 @@ from .factor import factorint
8
8
  from .dlp import dlog
9
9
  from .ec import EC_Weierstrass
10
10
  from .la import Matrix, zeros, eye
11
- from .lat import gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round_cvp, babai_plane_cvp, lagrange_lr, lll, random_unimodular_matrix
11
+ from .lat import gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round_cvp, babai_round_bnd, babai_plane_cvp, babai_plane_bnd, lagrange_lr, lll, random_unimodular_matrix
12
12
  from .poly import Poly
13
13
  from .Zmod import Zmod
@@ -4,7 +4,7 @@ Linear algebra
4
4
 
5
5
  from math import inf, sqrt, prod
6
6
  from numbers import Number
7
-
7
+ from fractions import Fraction
8
8
 
9
9
  class Matrix:
10
10
  """
@@ -99,12 +99,12 @@ class Matrix:
99
99
  return self.matrix == other.matrix
100
100
 
101
101
  def map(self, func):
102
- "Apply a function to all elements in place"
102
+ "Apply a function to all elements in place."
103
103
  for row in self.matrix:
104
104
  row[:] = map(func, row)
105
105
 
106
106
  def applyfunc(self, func):
107
- "Apply a function to all elements"
107
+ "Apply a function to all elements."
108
108
  tmp = self[:,:]
109
109
  tmp.map(func)
110
110
  return tmp
@@ -148,6 +148,8 @@ class Matrix:
148
148
  for j in range(other.cols):
149
149
  for k in range(other.rows):
150
150
  result.matrix[i][j] += self.matrix[i][k] * other.matrix[k][j]
151
+ if self.rows == 1 and other.cols == 1:
152
+ return result.matrix[0][0]
151
153
  return result
152
154
 
153
155
  def __add__(self, other) -> "Matrix":
@@ -176,7 +178,7 @@ class Matrix:
176
178
 
177
179
  def __rmul__(self, other) -> "Matrix":
178
180
  if isinstance(other, Number) or type(other) == type(self.matrix[0][0]):
179
- return Matrix([ [item * other for item in row] for row in self.matrix ])
181
+ return Matrix([ [item * other for item in row] for row in self.matrix ])
180
182
  return NotImplemented
181
183
 
182
184
  def rref(self) -> "Matrix":
@@ -246,6 +248,16 @@ class Matrix:
246
248
  raise ValueError("Matrix is not invertible!")
247
249
  return MM[:,n:]
248
250
 
251
+ def is_unimodular(self) -> bool:
252
+ "Test if the matrix is unimodular."
253
+ if self.rows != self.rows:
254
+ return False
255
+ def is_integer(i):
256
+ if isinstance(i, int) or (isinstance(i, Fraction) and i.denominator == 1):
257
+ return True
258
+ return False
259
+ return all([is_integer(i) for i in self]) and self.det()**2 == 1
260
+
249
261
  def zeros(self, m: int = None, n: int = None):
250
262
  "Returns a zero matrix of the same dimension"
251
263
  if not m and not n:
@@ -2,7 +2,7 @@
2
2
  Lattice tools
3
3
  """
4
4
 
5
- from math import prod
5
+ from math import prod, floor
6
6
  from fractions import Fraction
7
7
  from random import choice, sample
8
8
  from .la import Matrix, zeros
@@ -73,19 +73,28 @@ def hadamard_ratio(M: Matrix) -> float:
73
73
  return (gram_det(M) / prod([M[:, i].norm() for i in range(m)])) ** (1 / m)
74
74
 
75
75
  def babai_round_cvp(x: Matrix, U: Matrix) -> Matrix:
76
- "Babai's rounding algorithm for solving the CVP."
76
+ "Babai's rounding algorithm for approximately solving the CVP."
77
77
  s = U.inv() * x
78
78
  k = s.applyfunc(round)
79
79
  return U * k
80
80
 
81
+ def babai_round_bnd(U: Matrix) -> float:
82
+ "Bound for Babai's rounding algorithm for solving the CVP."
83
+ return floor(1 / (2 * max([ U.inv()[i,:].norm(1) for i in range(U.rows)])))
84
+
81
85
  def babai_plane_cvp(x: Matrix, U: Matrix) -> Matrix:
82
- "Babai's closest plane algorithm for solving the CVP."
86
+ "Babai's closest plane algorithm for approximately solving the CVP."
83
87
  Us = gram_schmidt(U)[0]
84
88
  y = x
85
89
  for k in range(U.cols - 1, -1, -1):
86
90
  y = y - round(y.dot(Us[:, k]) / norm2(Us[:, k])) * U[:, k]
87
91
  return (x - y).applyfunc(round)
88
92
 
93
+ def babai_plane_bnd(U: Matrix, p = 2) -> float:
94
+ "Bound for Babai's closest plane algorithm for solving the CVP."
95
+ Us = gram_schmidt(U)[0]
96
+ return float(0.5 * min([Us[:, i].norm(p) for i in range(Us.rows)]))
97
+
89
98
  def lagrange_lr(V: Matrix) -> Matrix:
90
99
  "Lagrange lattice reduction."
91
100
  assert (V.rows, V.cols) == (2, 2)
@@ -99,7 +108,7 @@ def lagrange_lr(V: Matrix) -> Matrix:
99
108
  return Matrix([list(v1), list(v3)]).transpose()
100
109
 
101
110
  def lll(V: Matrix, delta: float = 0.75, sort: bool = True) -> Matrix:
102
- "lll algorithm for lattice reduction"
111
+ "LLL algorithm for lattice reduction."
103
112
 
104
113
  assert 0 < delta <= 1, f"LLL reqires 0 < delta={delta} <= 1"
105
114
  j = 1
@@ -16,11 +16,11 @@ class Poly:
16
16
  """
17
17
 
18
18
  def __init__(self, coeff: list, ring = None, modulus: list = None):
19
- for i in range(len(coeff) - 1, 0, -1):
20
- if coeff[i]:
19
+ self.coeff = list(coeff)
20
+ for i in range(len(self.coeff) - 1, 0, -1):
21
+ if self.coeff[i]:
21
22
  break
22
- coeff.pop(i)
23
- self.coeff = coeff
23
+ self.coeff.pop(i)
24
24
  self.modulus = modulus
25
25
  if ring:
26
26
  self.map(ring)
@@ -86,18 +86,25 @@ class Poly:
86
86
  def __bool__(self):
87
87
  return bool(self.degree()) or bool(self.coeff[0])
88
88
 
89
- def degree(self):
89
+ def degree(self) -> int:
90
90
  "Return the degree."
91
91
  return len(self.coeff) - 1
92
92
 
93
93
  def map(self, func):
94
- "Apply a given function to all coefficients."
94
+ "Apply a given function to all coefficients in place."
95
95
  self.coeff = list(map(func, self.coeff))
96
96
 
97
+ def applyfunc(self, func) -> "Poly":
98
+ "Apply a function to all coefficients."
99
+ return self.__class__(list(map(func, self.coeff)), modulus=self.modulus)
100
+
101
+ def _check_type(self, other):
102
+ return isinstance(other, int) or (isinstance(other, Number) and isinstance(self.coeff[0], Number)) or type(other) == type(self.coeff[0])
103
+
97
104
  def __add__(self, other: "Poly") -> "Poly":
98
105
  if not isinstance(other, self.__class__):
99
- tmp = self.coeff[:]
100
- if isinstance(other, int) or type(other) == type(tmp[0]):
106
+ if self._check_type(other):
107
+ tmp = self.coeff[:]
101
108
  tmp[0] += other
102
109
  return self.__class__(tmp, modulus=self.modulus)
103
110
  return NotImplemented
@@ -117,7 +124,7 @@ class Poly:
117
124
 
118
125
  def __radd__(self, other: "Poly") -> "Poly":
119
126
  if not isinstance(other, self.__class__):
120
- if isinstance(other, Number) or type(other) == type(self.coeff[0]):
127
+ if self._check_type(other):
121
128
  tmp = self.coeff[:]
122
129
  tmp[0] += other
123
130
  return self.__class__(tmp, modulus=self.modulus)
@@ -126,9 +133,12 @@ class Poly:
126
133
  def __neg__(self) -> "Poly":
127
134
  return Poly([-s for s in self.coeff], modulus=self.modulus)
128
135
 
136
+ def __pos__(self) -> "Poly":
137
+ return self
138
+
129
139
  def __sub__(self, other: "Poly") -> "Poly":
130
140
  if not isinstance(other, self.__class__):
131
- if isinstance(other, int) or type(other) == type(self.coeff[0]):
141
+ if self._check_type(other):
132
142
  tmp = self.coeff[:]
133
143
  tmp[0] -= other
134
144
  return self.__class__(tmp, modulus=self.modulus)
@@ -149,7 +159,7 @@ class Poly:
149
159
 
150
160
  def __rsub__(self, other: "Poly") -> "Poly":
151
161
  if not isinstance(other, self.__class__):
152
- if isinstance(other, int) or type(other) == type(self.coeff[0]):
162
+ if self._check_type(other):
153
163
  tmp = self.coeff[:]
154
164
  tmp[0] -= other
155
165
  return self.__class__(tmp, modulus=self.modulus)
@@ -157,7 +167,7 @@ class Poly:
157
167
 
158
168
  def __mul__(self, other: "Poly") -> "Poly":
159
169
  if not isinstance(other, self.__class__):
160
- if isinstance(other, int) or type(other) == type(self.coeff[0]):
170
+ if self._check_type(other):
161
171
  return Poly([other * s for s in self.coeff], modulus = self.modulus)
162
172
  return NotImplemented
163
173
  ls, lo = len(self.coeff), len(other.coeff)
@@ -174,11 +184,25 @@ class Poly:
174
184
  modulus = other.modulus
175
185
  return self.__class__(coeff, modulus = modulus)
176
186
 
177
- def __rmul__(self, other: int) -> "Poly":
178
- if isinstance(other, int) or type(other) == type(self.coeff[0]):
187
+ def __rmul__(self, other) -> "Poly":
188
+ if self._check_type(other):
179
189
  return self.__class__([other * s for s in self.coeff], modulus=self.modulus)
180
190
  return NotImplemented
181
191
 
192
+ def __truediv__(self, other) -> "Poly":
193
+ if self._check_type(other):
194
+ return self.__class__([s / other for s in self.coeff], modulus=self.modulus)
195
+ if isinstance(other, self.__class__):
196
+ if not other.modulus:
197
+ raise NotImplementedError("Cannot invert polynomials without modulus.")
198
+ return self * other.inv()
199
+ return NotImplemented
200
+
201
+ def __rtruediv__(self, other) -> "Poly":
202
+ if not self.modulus:
203
+ raise NotImplementedError("Cannot invert polynomials without modulus.")
204
+ return other * self.inv()
205
+
182
206
  def __pow__(self, i: int) -> "Poly":
183
207
  if not isinstance(i, int):
184
208
  return NotImplemented
@@ -196,6 +220,14 @@ class Poly:
196
220
  res *= tmp
197
221
  return res
198
222
 
223
+ def max(self) -> int:
224
+ "Maximum of the absolute value of all coefficients."
225
+ return max([abs(c) for c in self.coeff])
226
+
227
+ def sum(self) -> int:
228
+ "Sum of the absolute value of all coefficients."
229
+ return sum([abs(c) for c in self.coeff])
230
+
199
231
  def __floordiv__(self, other: "Poly") -> "Poly":
200
232
  return self.divmod(other)[0]
201
233
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: kryptools
3
- Version: 0.5
3
+ Version: 0.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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "0.5"
3
+ version = "0.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
File without changes
File without changes
File without changes
File without changes