kryptools 0.1__tar.gz → 0.2__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.1 → kryptools-0.2}/PKG-INFO +5 -1
- {kryptools-0.1 → kryptools-0.2}/README.md +3 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/__init__.py +1 -1
- {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_ic.py +2 -1
- {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_qs.py +3 -2
- kryptools-0.2/kryptools/factor_dix.py +90 -0
- kryptools-0.2/kryptools/factor_fmt.py +30 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/lat.py +20 -6
- {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/PKG-INFO +5 -1
- {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/SOURCES.txt +2 -0
- {kryptools-0.1 → kryptools-0.2}/pyproject.toml +3 -2
- {kryptools-0.1 → kryptools-0.2}/LICENSE +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/Zmod.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/dlp.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_rho.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/ec.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/factor.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/factor_ecm.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/factor_pm1.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/factor_qs.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/la.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/nt.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/poly.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools/primes.py +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-0.1 → kryptools-0.2}/setup.cfg +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: kryptools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2
|
|
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
|
|
7
7
|
Project-URL: Issues, https://github.com/teschlg/kryptools/issues
|
|
8
|
+
Project-URL: Docs, https://github.com/teschlg/kryptools/doc
|
|
8
9
|
Classifier: Programming Language :: Python :: 3
|
|
9
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
11
|
Classifier: Operating System :: OS Independent
|
|
@@ -33,3 +34,6 @@ The tools contained are:
|
|
|
33
34
|
* Matrix: a class for Matrices (inverse, det, reduced echelon form, etc.)
|
|
34
35
|
* Poly: a class for polynomials (division, modulo)
|
|
35
36
|
* Zmod: a class for the ring of integers modulo an integer
|
|
37
|
+
|
|
38
|
+
Documentation can be found in the jupyter notebook
|
|
39
|
+
(currently incomplete: use the force, read the source).
|
|
@@ -19,3 +19,6 @@ The tools contained are:
|
|
|
19
19
|
* Matrix: a class for Matrices (inverse, det, reduced echelon form, etc.)
|
|
20
20
|
* Poly: a class for polynomials (division, modulo)
|
|
21
21
|
* Zmod: a class for the ring of integers modulo an integer
|
|
22
|
+
|
|
23
|
+
Documentation can be found in the jupyter notebook
|
|
24
|
+
(currently incomplete: use the force, read the source).
|
|
@@ -6,7 +6,7 @@ from .dlp import dlog
|
|
|
6
6
|
from .ec import EC_Weierstrass
|
|
7
7
|
from .factor import factorint
|
|
8
8
|
from .la import Matrix
|
|
9
|
-
from .lat import hermite_nf, gram_schmidt, lll
|
|
9
|
+
from .lat import gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round_cvp, babai_plane_cvp, lagrange_lr, lll
|
|
10
10
|
from .nt import cf, convergents, jacobi_symbol, sqrt_mod, euler_phi, order, carmichael_lambda
|
|
11
11
|
from .poly import Poly
|
|
12
12
|
from .primes import sieve_eratosthenes, isprime
|
|
@@ -3,9 +3,10 @@ Discrete log solvers: Index calculus
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from math import gcd
|
|
6
|
-
from random import randint
|
|
6
|
+
from random import randint, seed
|
|
7
7
|
from .primes import sieve_eratosthenes
|
|
8
8
|
from .dlp_qs import determine_factorbound, determine_trialdivison_bounds, is_smooth
|
|
9
|
+
seed(0)
|
|
9
10
|
|
|
10
11
|
def dlog_ic(a: int, b: int, n: int, m: int, pollard: bool = True, verbose: int = 0) -> int:
|
|
11
12
|
"""Compute the discrete log_a(b) in Z_p of an element a of prime order m using Index Calculus."""
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
Discrete log solvers: Quadratic sieve
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from math import exp, log, sqrt, gcd, isqrt
|
|
6
|
+
from random import randint, seed
|
|
5
7
|
from .nt import sqrt_mod
|
|
6
8
|
from .primes import sieve_eratosthenes
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
seed(0)
|
|
9
10
|
|
|
10
11
|
def determine_factorbound(n: int) -> (int, int):
|
|
11
12
|
"""Determines the optimal factor bound and the expected number of trys until a for a given n."""
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integer factorization: Dixon's method
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from math import isqrt, gcd, sqrt, log, exp, ceil
|
|
6
|
+
from .primes import sieve_eratosthenes
|
|
7
|
+
from .nt import legendre_symbol, sqrt_mod
|
|
8
|
+
from .factor_qs import bytexor, byteset, bytetest
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def factor_dixon(n: int) -> list:
|
|
12
|
+
"""Find factors of n using the method of Dixon."""
|
|
13
|
+
# first determine the bound B for the factorbase: Choosing B=p^(1/u) Canfield-Erdös-Pomerance gives us
|
|
14
|
+
# 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
|
|
15
|
+
# we use Newton
|
|
16
|
+
u = 2 * sqrt(log(n) / log(log(n))) # asymptotic value
|
|
17
|
+
for _ in range(3):
|
|
18
|
+
u = (2 * log(n) + u * u * (2 + log(u))) / (
|
|
19
|
+
2 + 3 * u + 2 * u * log(u)
|
|
20
|
+
) # Newton iteration
|
|
21
|
+
B = int(exp(log(n) / u))
|
|
22
|
+
|
|
23
|
+
# B = int(exp(0.5 * sqrt( log(n) * log(log(n)) )*( 1 + 1/log(log(n)) )))
|
|
24
|
+
factorbase = []
|
|
25
|
+
for p in sieve_eratosthenes(B): # compute the factorbase
|
|
26
|
+
ls = legendre_symbol(n, p)
|
|
27
|
+
if ls == 0: # we already found a factor;-)
|
|
28
|
+
if n == p:
|
|
29
|
+
return n
|
|
30
|
+
return p
|
|
31
|
+
if ls == 1: # we only take primes such that n is quadratic residue
|
|
32
|
+
factorbase.append(p)
|
|
33
|
+
lf = len(factorbase) + 1 # length of the factorbase (including -1)
|
|
34
|
+
lfb = ceil(lf / 8) # the number of bytes we need to store a relation
|
|
35
|
+
m = isqrt(n - 1) + 1
|
|
36
|
+
def process_relation(j: int, relation: bytes):
|
|
37
|
+
nonlocal relation_no, values, relations
|
|
38
|
+
relation_no += 1
|
|
39
|
+
rhs = bytearray(b"\x00") * lfb # construct the k'th row of the identity matrix
|
|
40
|
+
byteset(rhs, relation_no)
|
|
41
|
+
relation += rhs # extend the relation with this row
|
|
42
|
+
values[relation_no] = j # store the value which lead to the relation
|
|
43
|
+
# do the Gauss elimination
|
|
44
|
+
index = lf # this will be the index of the first nonzero entry
|
|
45
|
+
# print(f'{j:3}', ' '.join(f'{b:08b}' for b in reversed(relation)))
|
|
46
|
+
for i in range(lf):
|
|
47
|
+
if bytetest(relation, i) and relations[i] != None: # make this entry zero if we can (Gauss elimination)
|
|
48
|
+
bytexor(relation, relations[i])
|
|
49
|
+
if bytetest(relation, i) and index == lf: # is this the index of the first nonzero entry?
|
|
50
|
+
index = i
|
|
51
|
+
# print(f'{j:3}', ' '.join(f'{b:08b}' for b in reversed(relation)))
|
|
52
|
+
if index == lf: # the new relation is linearly dependent: we have found a linear combination of the 0 vector
|
|
53
|
+
# now we need to determine the factors
|
|
54
|
+
u = 1 # product over all values m - j such that f(m-j) is B-smooth
|
|
55
|
+
v = 1 # sqrt of the product over all f(m-j) which are B-smooth
|
|
56
|
+
w = 1 # save nonsquare terms for the next round
|
|
57
|
+
for i in range(lf):
|
|
58
|
+
if bytetest(relation, lfb * 8 + i): # select the relations which sum to the 0 vector
|
|
59
|
+
ui = m + values[i]
|
|
60
|
+
u = (u * ui) % n
|
|
61
|
+
vi = ui ** 2 - n
|
|
62
|
+
d = gcd(w, vi)
|
|
63
|
+
v = (v * d) % n # sqrt of the part which is already square
|
|
64
|
+
w = (w // d) * (vi // d) # this part is not square yet
|
|
65
|
+
v = v * isqrt(w) % n
|
|
66
|
+
res = gcd(u - v, n)
|
|
67
|
+
if 1 < res < n:
|
|
68
|
+
return res
|
|
69
|
+
relation_no -= 1 # this one did not work, try again
|
|
70
|
+
else:
|
|
71
|
+
relations[index] = relation
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
relation_no = -1
|
|
75
|
+
relations = [None] * lf # here we will store the relations in case we found a B-smooth number
|
|
76
|
+
values = [None] * lf # here we will store the values leading to the B-smooth numbers
|
|
77
|
+
for j in range(1,m): # loop over j=0,1,-1,2,-2,...
|
|
78
|
+
if j & 1 == 0:
|
|
79
|
+
j >>= 1
|
|
80
|
+
else:
|
|
81
|
+
j >>= 1
|
|
82
|
+
j *= -1
|
|
83
|
+
relation = is_smooth((j + m) ** 2 - n, factorbase, lfb) # test if f(j) is B-smooth
|
|
84
|
+
if relation is None:
|
|
85
|
+
continue
|
|
86
|
+
res = process_relation(j, relation)
|
|
87
|
+
if res:
|
|
88
|
+
return(res)
|
|
89
|
+
return n
|
|
90
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Integer factorization: Fermat's method
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from math import isqrt
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def factor_fermat(n: int) -> list:
|
|
9
|
+
"""Find factors of n using the method of Fermat."""
|
|
10
|
+
factors = []
|
|
11
|
+
# Fermat only works if n has two factors which are either both even or both odd
|
|
12
|
+
while n % 2 == 0:
|
|
13
|
+
factors.append(2)
|
|
14
|
+
n //= 2
|
|
15
|
+
a = isqrt(n - 1) + 1
|
|
16
|
+
step =2
|
|
17
|
+
if n % 3 == 2: # if n % 3 = 2, then a must be a multiple of 3
|
|
18
|
+
a += 2 - ((a - 1) % 3)
|
|
19
|
+
step = 3
|
|
20
|
+
elif (n % 4 == 1) ^ (a & 1): # if n % 4 = 1,3 then a must be odd, even, respectively
|
|
21
|
+
a += 1
|
|
22
|
+
while a <= (n + 9) // 6:
|
|
23
|
+
b = isqrt(a * a - n)
|
|
24
|
+
if b * b == a * a - n:
|
|
25
|
+
factors.append(a - b)
|
|
26
|
+
factors.append(a + b)
|
|
27
|
+
return factors
|
|
28
|
+
a += step
|
|
29
|
+
factors.append(n)
|
|
30
|
+
return factors
|
|
@@ -6,12 +6,6 @@ from math import prod
|
|
|
6
6
|
from fractions import Fraction
|
|
7
7
|
from .la import Matrix, zeros, eye
|
|
8
8
|
|
|
9
|
-
def babai_round_cvp(x: Matrix, U: Matrix) -> Matrix:
|
|
10
|
-
"Babai's rounding algorithm for solving the CVP."
|
|
11
|
-
s = U.inv() * x
|
|
12
|
-
k = s.map(round)
|
|
13
|
-
return U * k
|
|
14
|
-
|
|
15
9
|
def hermite_nf(M: Matrix) -> Matrix:
|
|
16
10
|
"Compute the Hermite normal form of a matrix M."
|
|
17
11
|
n, m = M.cols, M.rows
|
|
@@ -68,13 +62,21 @@ def gram_schmidt(U: Matrix) -> (Matrix, Matrix):
|
|
|
68
62
|
return Us, M
|
|
69
63
|
|
|
70
64
|
def gram_det(U: Matrix) -> float:
|
|
65
|
+
"Compute the Gram determinant of a matrix."
|
|
71
66
|
Us = gram_schmidt(U)[0]
|
|
72
67
|
return prod([Us[:, i].norm() for i in range(U.rows)])
|
|
73
68
|
|
|
74
69
|
def hadamard_ratio(M: Matrix) -> float:
|
|
70
|
+
"Compute the Hadamard ratio of a matrix."
|
|
75
71
|
m = M.rows
|
|
76
72
|
return (gram_det(M) / prod([M[:, i].norm() for i in range(m)])) ** (1 / m)
|
|
77
73
|
|
|
74
|
+
def babai_round_cvp(x: Matrix, U: Matrix) -> Matrix:
|
|
75
|
+
"Babai's rounding algorithm for solving the CVP."
|
|
76
|
+
s = U.inv() * x
|
|
77
|
+
k = s.applyfunc(round)
|
|
78
|
+
return U * k
|
|
79
|
+
|
|
78
80
|
def babai_plane_cvp(x: Matrix, U: Matrix) -> Matrix:
|
|
79
81
|
"Babai's closest plane algorithm for solving the CVP."
|
|
80
82
|
Us = gram_schmidt(U)[0]
|
|
@@ -83,6 +85,18 @@ def babai_plane_cvp(x: Matrix, U: Matrix) -> Matrix:
|
|
|
83
85
|
y = y - round(y.dot(Us[:, k]) / norm2(Us[:, k])) * U[:, k]
|
|
84
86
|
return (x - y).applyfunc(round)
|
|
85
87
|
|
|
88
|
+
def lagrange_lr(V: Matrix) -> Matrix:
|
|
89
|
+
"Lagrange lattice reduction."
|
|
90
|
+
assert (V.rows, V.cols) == (2, 2)
|
|
91
|
+
v1, v2 = V[:, 0], V[:, 1]
|
|
92
|
+
if norm2(v1) > norm2(v2):
|
|
93
|
+
v1, v2 = v2, v1
|
|
94
|
+
v3 = v2 - round(v1.dot(v2) / norm2(v1)) * v1
|
|
95
|
+
while norm2(v3) < norm2(v1):
|
|
96
|
+
v2, v1 = v1, v3
|
|
97
|
+
v3 = v2 - round(v1.dot(v2) / norm2(v1)) * v1
|
|
98
|
+
return Matrix([list(v1), list(v3)]).transpose()
|
|
99
|
+
|
|
86
100
|
def lll(V: Matrix, delta: float = 0.75, sort: bool = True) -> Matrix:
|
|
87
101
|
"lll algorithm for lattice reduction"
|
|
88
102
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: kryptools
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2
|
|
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
|
|
7
7
|
Project-URL: Issues, https://github.com/teschlg/kryptools/issues
|
|
8
|
+
Project-URL: Docs, https://github.com/teschlg/kryptools/doc
|
|
8
9
|
Classifier: Programming Language :: Python :: 3
|
|
9
10
|
Classifier: License :: OSI Approved :: MIT License
|
|
10
11
|
Classifier: Operating System :: OS Independent
|
|
@@ -33,3 +34,6 @@ The tools contained are:
|
|
|
33
34
|
* Matrix: a class for Matrices (inverse, det, reduced echelon form, etc.)
|
|
34
35
|
* Poly: a class for polynomials (division, modulo)
|
|
35
36
|
* Zmod: a class for the ring of integers modulo an integer
|
|
37
|
+
|
|
38
|
+
Documentation can be found in the jupyter notebook
|
|
39
|
+
(currently incomplete: use the force, read the source).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "kryptools"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Gerald Teschl", email="gerald.teschl@univie.ac.at" },
|
|
6
6
|
]
|
|
@@ -15,4 +15,5 @@ classifiers = [
|
|
|
15
15
|
|
|
16
16
|
[project.urls]
|
|
17
17
|
Homepage = "https://github.com/teschlg/kryptools"
|
|
18
|
-
Issues = "https://github.com/teschlg/kryptools/issues"
|
|
18
|
+
Issues = "https://github.com/teschlg/kryptools/issues"
|
|
19
|
+
Docs = "https://github.com/teschlg/kryptools/doc"
|
|
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
|