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.
- {kryptools-0.5 → kryptools-0.7}/PKG-INFO +1 -1
- {kryptools-0.5 → kryptools-0.7}/kryptools/Zmod.py +6 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/__init__.py +1 -1
- {kryptools-0.5 → kryptools-0.7}/kryptools/la.py +16 -4
- {kryptools-0.5 → kryptools-0.7}/kryptools/lat.py +13 -4
- {kryptools-0.5 → kryptools-0.7}/kryptools/poly.py +46 -14
- {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/PKG-INFO +1 -1
- {kryptools-0.5 → kryptools-0.7}/pyproject.toml +1 -1
- {kryptools-0.5 → kryptools-0.7}/LICENSE +0 -0
- {kryptools-0.5 → kryptools-0.7}/README.md +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/dlp.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_ic.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_qs.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/dlp_rho.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/ec.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/factor.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/factor_dix.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/factor_ecm.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/factor_fmt.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/factor_pm1.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/factor_qs.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/nt.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools/primes.py +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/SOURCES.txt +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-0.5 → kryptools-0.7}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-0.5 → kryptools-0.7}/setup.cfg +0 -0
|
@@ -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
|
-
|
|
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
|
-
"
|
|
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
|
-
|
|
20
|
-
|
|
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
|
-
|
|
100
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
178
|
-
if
|
|
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
|
|
|
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
|