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.
Files changed (28) hide show
  1. {kryptools-0.1 → kryptools-0.2}/PKG-INFO +5 -1
  2. {kryptools-0.1 → kryptools-0.2}/README.md +3 -0
  3. {kryptools-0.1 → kryptools-0.2}/kryptools/__init__.py +1 -1
  4. {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_ic.py +2 -1
  5. {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_qs.py +3 -2
  6. kryptools-0.2/kryptools/factor_dix.py +90 -0
  7. kryptools-0.2/kryptools/factor_fmt.py +30 -0
  8. {kryptools-0.1 → kryptools-0.2}/kryptools/lat.py +20 -6
  9. {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/PKG-INFO +5 -1
  10. {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/SOURCES.txt +2 -0
  11. {kryptools-0.1 → kryptools-0.2}/pyproject.toml +3 -2
  12. {kryptools-0.1 → kryptools-0.2}/LICENSE +0 -0
  13. {kryptools-0.1 → kryptools-0.2}/kryptools/Zmod.py +0 -0
  14. {kryptools-0.1 → kryptools-0.2}/kryptools/dlp.py +0 -0
  15. {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_bsgs.py +0 -0
  16. {kryptools-0.1 → kryptools-0.2}/kryptools/dlp_rho.py +0 -0
  17. {kryptools-0.1 → kryptools-0.2}/kryptools/ec.py +0 -0
  18. {kryptools-0.1 → kryptools-0.2}/kryptools/factor.py +0 -0
  19. {kryptools-0.1 → kryptools-0.2}/kryptools/factor_ecm.py +0 -0
  20. {kryptools-0.1 → kryptools-0.2}/kryptools/factor_pm1.py +0 -0
  21. {kryptools-0.1 → kryptools-0.2}/kryptools/factor_qs.py +0 -0
  22. {kryptools-0.1 → kryptools-0.2}/kryptools/la.py +0 -0
  23. {kryptools-0.1 → kryptools-0.2}/kryptools/nt.py +0 -0
  24. {kryptools-0.1 → kryptools-0.2}/kryptools/poly.py +0 -0
  25. {kryptools-0.1 → kryptools-0.2}/kryptools/primes.py +0 -0
  26. {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/dependency_links.txt +0 -0
  27. {kryptools-0.1 → kryptools-0.2}/kryptools.egg-info/top_level.txt +0 -0
  28. {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.1
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
- from math import exp, log, sqrt, gcd
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.1
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).
@@ -10,7 +10,9 @@ kryptools/dlp_qs.py
10
10
  kryptools/dlp_rho.py
11
11
  kryptools/ec.py
12
12
  kryptools/factor.py
13
+ kryptools/factor_dix.py
13
14
  kryptools/factor_ecm.py
15
+ kryptools/factor_fmt.py
14
16
  kryptools/factor_pm1.py
15
17
  kryptools/factor_qs.py
16
18
  kryptools/la.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "0.1"
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