kryptools 1.2__tar.gz → 1.3__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 (57) hide show
  1. {kryptools-1.2 → kryptools-1.3}/PKG-INFO +3 -1
  2. {kryptools-1.2 → kryptools-1.3}/README.md +2 -0
  3. {kryptools-1.2 → kryptools-1.3}/kryptools/Zmod.py +5 -1
  4. {kryptools-1.2 → kryptools-1.3}/kryptools/__init__.py +2 -1
  5. kryptools-1.3/kryptools/code.py +124 -0
  6. {kryptools-1.2 → kryptools-1.3}/kryptools/la.py +1 -1
  7. {kryptools-1.2 → kryptools-1.3}/kryptools/lat.py +2 -1
  8. {kryptools-1.2 → kryptools-1.3}/kryptools/poly.py +10 -0
  9. {kryptools-1.2 → kryptools-1.3}/kryptools.egg-info/PKG-INFO +3 -1
  10. {kryptools-1.2 → kryptools-1.3}/kryptools.egg-info/SOURCES.txt +2 -0
  11. {kryptools-1.2 → kryptools-1.3}/pyproject.toml +1 -1
  12. kryptools-1.3/tests/test_code.py +32 -0
  13. {kryptools-1.2 → kryptools-1.3}/LICENSE +0 -0
  14. {kryptools-1.2 → kryptools-1.3}/kryptools/GF2.py +0 -0
  15. {kryptools-1.2 → kryptools-1.3}/kryptools/aes.py +0 -0
  16. {kryptools-1.2 → kryptools-1.3}/kryptools/blockcipher.py +0 -0
  17. {kryptools-1.2 → kryptools-1.3}/kryptools/conway_polynomials.py +0 -0
  18. {kryptools-1.2 → kryptools-1.3}/kryptools/des.py +0 -0
  19. {kryptools-1.2 → kryptools-1.3}/kryptools/dlp.py +0 -0
  20. {kryptools-1.2 → kryptools-1.3}/kryptools/dlp_bsgs.py +0 -0
  21. {kryptools-1.2 → kryptools-1.3}/kryptools/dlp_ic.py +0 -0
  22. {kryptools-1.2 → kryptools-1.3}/kryptools/dlp_qs.py +0 -0
  23. {kryptools-1.2 → kryptools-1.3}/kryptools/dlp_rho.py +0 -0
  24. {kryptools-1.2 → kryptools-1.3}/kryptools/ec.py +0 -0
  25. {kryptools-1.2 → kryptools-1.3}/kryptools/factor.py +0 -0
  26. {kryptools-1.2 → kryptools-1.3}/kryptools/factor_dix.py +0 -0
  27. {kryptools-1.2 → kryptools-1.3}/kryptools/factor_ecm.py +0 -0
  28. {kryptools-1.2 → kryptools-1.3}/kryptools/factor_fmt.py +0 -0
  29. {kryptools-1.2 → kryptools-1.3}/kryptools/factor_pm1.py +0 -0
  30. {kryptools-1.2 → kryptools-1.3}/kryptools/factor_qs.py +0 -0
  31. {kryptools-1.2 → kryptools-1.3}/kryptools/factor_rho.py +0 -0
  32. {kryptools-1.2 → kryptools-1.3}/kryptools/intfuncs.py +0 -0
  33. {kryptools-1.2 → kryptools-1.3}/kryptools/keccak.py +0 -0
  34. {kryptools-1.2 → kryptools-1.3}/kryptools/nt.py +0 -0
  35. {kryptools-1.2 → kryptools-1.3}/kryptools/primes.py +0 -0
  36. {kryptools-1.2 → kryptools-1.3}/kryptools/sha1.py +0 -0
  37. {kryptools-1.2 → kryptools-1.3}/kryptools.egg-info/dependency_links.txt +0 -0
  38. {kryptools-1.2 → kryptools-1.3}/kryptools.egg-info/top_level.txt +0 -0
  39. {kryptools-1.2 → kryptools-1.3}/setup.cfg +0 -0
  40. {kryptools-1.2 → kryptools-1.3}/tests/test_GF2.py +0 -0
  41. {kryptools-1.2 → kryptools-1.3}/tests/test_Zmod.py +0 -0
  42. {kryptools-1.2 → kryptools-1.3}/tests/test_aes.py +0 -0
  43. {kryptools-1.2 → kryptools-1.3}/tests/test_des.py +0 -0
  44. {kryptools-1.2 → kryptools-1.3}/tests/test_dlog.py +0 -0
  45. {kryptools-1.2 → kryptools-1.3}/tests/test_ec.py +0 -0
  46. {kryptools-1.2 → kryptools-1.3}/tests/test_factor.py +0 -0
  47. {kryptools-1.2 → kryptools-1.3}/tests/test_factor_fmt.py +0 -0
  48. {kryptools-1.2 → kryptools-1.3}/tests/test_factor_pm1.py +0 -0
  49. {kryptools-1.2 → kryptools-1.3}/tests/test_factor_qs.py +0 -0
  50. {kryptools-1.2 → kryptools-1.3}/tests/test_intfuncs.py +0 -0
  51. {kryptools-1.2 → kryptools-1.3}/tests/test_keccak.py +0 -0
  52. {kryptools-1.2 → kryptools-1.3}/tests/test_la.py +0 -0
  53. {kryptools-1.2 → kryptools-1.3}/tests/test_lat.py +0 -0
  54. {kryptools-1.2 → kryptools-1.3}/tests/test_nt.py +0 -0
  55. {kryptools-1.2 → kryptools-1.3}/tests/test_poly.py +0 -0
  56. {kryptools-1.2 → kryptools-1.3}/tests/test_primes.py +0 -0
  57. {kryptools-1.2 → kryptools-1.3}/tests/test_sha1.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryptools
3
- Version: 1.2
3
+ Version: 1.3
4
4
  Summary: Implemenation of same basic algorithms used in cryptography.
5
5
  Author-email: Gerald Teschl <gerald.teschl@univie.ac.at>
6
6
  License: MIT
@@ -39,11 +39,13 @@ The tools contained are:
39
39
  * elliptic curves (Weierstrass form), group operations, order, discrete logarithms
40
40
  * linear algebra: Hermite normal form, Gram-Schmidt
41
41
  * lattices: Hadamard ratio, Babai rounding/nearest plane algorithm, lattice reduction (Lenstra-Lenstra-Lovaz)
42
+ * linear codes: Hamming distance, left standard form, parity check matrix
42
43
 
43
44
  * Matrix: a class for Matrices (inverse, det, reduced echelon form, etc.)
44
45
  * Poly: a class for polynomials (division, modulo)
45
46
  * Zmod: a class for the ring of integers modulo an integer
46
47
  * GF2: a class for Galois fields GF(2^n)
48
+ * Goppa: a class for encoding and decoding Goppa codes
47
49
 
48
50
  * BlockCipher: a class implementing the usual modes of operation (ECB, CBC, GCM, etc.)
49
51
  * AESCipher: individual AES operations
@@ -21,11 +21,13 @@ The tools contained are:
21
21
  * elliptic curves (Weierstrass form), group operations, order, discrete logarithms
22
22
  * linear algebra: Hermite normal form, Gram-Schmidt
23
23
  * lattices: Hadamard ratio, Babai rounding/nearest plane algorithm, lattice reduction (Lenstra-Lenstra-Lovaz)
24
+ * linear codes: Hamming distance, left standard form, parity check matrix
24
25
 
25
26
  * Matrix: a class for Matrices (inverse, det, reduced echelon form, etc.)
26
27
  * Poly: a class for polynomials (division, modulo)
27
28
  * Zmod: a class for the ring of integers modulo an integer
28
29
  * GF2: a class for Galois fields GF(2^n)
30
+ * Goppa: a class for encoding and decoding Goppa codes
29
31
 
30
32
  * BlockCipher: a class implementing the usual modes of operation (ECB, CBC, GCM, etc.)
31
33
  * AESCipher: individual AES operations
@@ -17,7 +17,7 @@ class Zmod:
17
17
  To define a finite Galois field modulo the prime 5 use
18
18
  >>> Z_5=Zmod(5)
19
19
 
20
- To declare 3 as an element of our Galois filed use
20
+ To declare 3 as an element of our Galois field use
21
21
  >>> Z_5(3)
22
22
  3
23
23
 
@@ -210,6 +210,10 @@ class ZmodPoint:
210
210
  def __abs__(self) -> int:
211
211
  return abs(self.sharp())
212
212
 
213
+ def bits(self) -> list:
214
+ "Convert to a list of bits."
215
+ return [int(d) for d in str(format(self.x, "0" + str(int.bit_length(self.ring.n - 1)) + "b"))]
216
+
213
217
  def sharp(self):
214
218
  "Returns a symmetric (w.r.t. 0) representative."
215
219
  tmp = (self.ring.n - 1) // 2
@@ -5,7 +5,7 @@ Implemenation of same basic algorithms used in cryptography.
5
5
  __author__ = "Gerald Teschl"
6
6
  __copyright__ = "Copyright 2024-2025, Gerald Teschl"
7
7
  __license__ = "MIT License"
8
- __version__ = "1.2"
8
+ __version__ = "1.3"
9
9
  __email__ = "Gerald.Teschl@univie.ac.at"
10
10
 
11
11
  from .nt import egcd, cf, convergents, legendre_symbol, jacobi_symbol, sqrt_mod, euler_phi, carmichael_lambda, moebius_mu, is_carmichael_number, order, crt
@@ -19,6 +19,7 @@ from .lat import gram_det, hadamard_ratio, hermite_nf, gram_schmidt, babai_round
19
19
  from .poly import Poly
20
20
  from .Zmod import Zmod
21
21
  from .GF2 import GF2, GF2_aes, GF2_miniaes, GF2_ghash
22
+ from .code import left_standard_form, gen2pchk, hamming_dist, Goppa
22
23
  from .blockcipher import BlockCipher, bytexor
23
24
  from .aes import AESKeySchedule, AESCipher, AESBlockCipher
24
25
  from .des import list2int, int2list, permute, invert_permutation, rotate_left, SDESKeySchedule, SDESCipher, DESKeySchedule, DESCipher, DESBlockCipher
@@ -0,0 +1,124 @@
1
+ """
2
+ Linear codes
3
+ """
4
+
5
+ from .Zmod import Zmod
6
+ from .GF2 import GF2
7
+ from .poly import Poly
8
+ from .la import Matrix, eye, zeros
9
+
10
+
11
+ def poly2bits(x: Poly) -> list:
12
+ "Convert a polynomial in GF(2^n)[x] to a list of binary digits."
13
+ out = []
14
+ for c in x.coeff:
15
+ out += c.bits()
16
+ return out
17
+
18
+ def left_standard_form(M: Matrix) -> (Matrix, Matrix):
19
+ "Compute the left standard form of a generator matrix. Return the standard form and the pertmutation matrix."
20
+ M = M.rref()
21
+ for i in range(M.rows-1,-1,-1):
22
+ if not M[i,:]:
23
+ M.delete_rows(i) # remove zero rows
24
+ last = min(M.rows, M.cols)
25
+ P = eye(M.cols)
26
+ for i in range(last):
27
+ if not M[i,i]:
28
+ j = i + 1
29
+ while j <= last and not M[i, j]:
30
+ j += 1
31
+ if j <= last:
32
+ P[:,i], P[:,j] = P[:,j], P[:,i]
33
+ M[:,i], M[:,j] = M[:,j], M[:,i]
34
+ return M, P
35
+
36
+ def gen2pchk(G: Matrix) -> Matrix:
37
+ "Compute the parity check matrix from a given generator matrix (and vice versa)."
38
+ G, P = left_standard_form(G)
39
+ d = G.cols - G.rows
40
+ assert d > 0
41
+ zero = 0 * G[0]
42
+ H = zeros(d, G.cols, zero = zero)
43
+ for i in range(d):
44
+ H[i,G.rows+i] = zero**0
45
+ tmp = - G[:,-d:].transpose()
46
+ for i in range(G.cols - d):
47
+ H[:, i] = tmp[:, i]
48
+ return H * P.transpose()
49
+
50
+ def hamming_dist(a: iter, b: iter):
51
+ "Hamming distance of two iterables."
52
+ if len(a) != len(b):
53
+ raise ValueError("Both iteralbles must have equal length.")
54
+ return sum(aa != bb for aa, bb in zip(a, b))
55
+
56
+ class Goppa():
57
+ """
58
+ Binary Goppa code.
59
+
60
+ Example:
61
+
62
+ >>> gf = GF2(4) # base field GF(2^n)
63
+ >>> g = Poly([2, 0, 0, 1], ring = gf) # Polynomial for the code
64
+ >>> alpha = list(gf) # list of points from the base field (must not contain zeros of g)
65
+ >>> goppa = Goppa(gf, g, alpha)
66
+
67
+ To encode a list of bits (the length must be equal to the dimension k of the code)
68
+ >>> goppa.encode([1, 0, 1, 1])
69
+ [0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1]
70
+
71
+ Decoding still works if there are atmost deg(g) errors:
72
+ >>> goppa.decode([0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0])
73
+ [1, 0, 1, 1]
74
+
75
+ """
76
+
77
+ def __init__(self, gf: GF2, g: Poly, alpha: list["GF2Point"]):
78
+ assert all(map(g, alpha))
79
+ self.gf = gf
80
+ self.g = g
81
+ self.alpha = alpha
82
+ # Compute the control matrix
83
+ self.Z_2 = Zmod(2)
84
+
85
+ tmp =[]
86
+ for x in alpha:
87
+ tmp.append(Poly([-x, 1], ring = gf, modulus = g).inv().bits())
88
+ self.H = Matrix(tmp, ring=self.Z_2).transpose()
89
+ # Compute the generator matrix
90
+ self.G = gen2pchk(self.H)
91
+
92
+ def encode(self, x: list[int]):
93
+ "Encode a given list of bits."
94
+ x = Matrix(x, ring = self.Z_2)
95
+ y = self.G.transpose() * x
96
+ y.map(int)
97
+ return list(y)
98
+
99
+ def decode(self, y: list[int]):
100
+ "Decode a given list of bits."
101
+ y = Matrix(y, ring = self.Z_2)
102
+ if self.H * y: # no code word
103
+ s = self.gf(0) # syndrom polynomial
104
+ for i, x in enumerate(self.alpha):
105
+ s += int(y[i]) * Poly([-x, 1], ring = self.gf, modulus = self.g).inv()
106
+ v = (s.inv() - Poly([0, 1], ring = self.gf, modulus = self.g))**(self.gf.order ** self.g.degree() // 2)
107
+ # determine error locator polynomial sigma(x) = a(x^2) + b(x^2) * x
108
+ # find a and b by running EEA until b has the desired degree
109
+ v.modulus = None
110
+ r0, r1 = self.g, v
111
+ y0, y1 = Poly([self.gf(0)]), Poly([self.gf(1)])
112
+ while r1 and 2* r1.degree() > self.g.degree():
113
+ q, r = r0.divmod(r1)
114
+ r0, r1 = r1, r
115
+ y0, y1 = y1, y0 - q * y1
116
+ a, b = r1, y1
117
+ sigma = a**2 + b**2 * Poly([0,1], ring = self.gf)
118
+ # correct the error
119
+ for x in self.gf:
120
+ if not sigma(x):
121
+ y[int(x)] += 1
122
+ x = self.G.transpose().solve(y)
123
+ x.map(int)
124
+ return list(x)
@@ -374,7 +374,7 @@ class Matrix:
374
374
  A[:, 0:self.cols] = self
375
375
  A[:, self.cols] = b
376
376
  A = A.rref()
377
- solution = self.zeros(self.rows, 1)
377
+ solution = self.zeros(self.cols, 1)
378
378
  for i in range(A.rows-1, -1, -1):
379
379
  if not any(A.matrix[i][:-1]):
380
380
  if A.matrix[i][-1]:
@@ -109,7 +109,8 @@ def babai_plane_bnd(U: Matrix, p=2) -> float:
109
109
 
110
110
  def lagrange_lr(V: Matrix) -> Matrix:
111
111
  "Lagrange lattice reduction."
112
- assert (V.rows, V.cols) == (2, 2)
112
+ if (V.rows, V.cols) != (2, 2):
113
+ raise ValueError("Lagrange lattice reduction requires dimension two.")
113
114
  v1, v2 = V[:, 0], V[:, 1]
114
115
  if norm2(v1) > norm2(v2):
115
116
  v1, v2 = v2, v1
@@ -231,6 +231,16 @@ class Poly:
231
231
  tmp *= tmp
232
232
  return res
233
233
 
234
+ def bits(self) -> list[int]:
235
+ "List of bits of all coefficients."
236
+ ring = self.coeff[0].__class__
237
+ if not (hasattr(ring, 'bits') and callable(ring.bits)):
238
+ raise NotImplementedError("Coefficients cannot be converted to bits.")
239
+ out = []
240
+ for c in self.coeff:
241
+ out += c.bits()
242
+ return out
243
+
234
244
  def max(self) -> int:
235
245
  "Maximum of the absolute value of all coefficients."
236
246
  return max(abs(c) for c in self.coeff)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryptools
3
- Version: 1.2
3
+ Version: 1.3
4
4
  Summary: Implemenation of same basic algorithms used in cryptography.
5
5
  Author-email: Gerald Teschl <gerald.teschl@univie.ac.at>
6
6
  License: MIT
@@ -39,11 +39,13 @@ The tools contained are:
39
39
  * elliptic curves (Weierstrass form), group operations, order, discrete logarithms
40
40
  * linear algebra: Hermite normal form, Gram-Schmidt
41
41
  * lattices: Hadamard ratio, Babai rounding/nearest plane algorithm, lattice reduction (Lenstra-Lenstra-Lovaz)
42
+ * linear codes: Hamming distance, left standard form, parity check matrix
42
43
 
43
44
  * Matrix: a class for Matrices (inverse, det, reduced echelon form, etc.)
44
45
  * Poly: a class for polynomials (division, modulo)
45
46
  * Zmod: a class for the ring of integers modulo an integer
46
47
  * GF2: a class for Galois fields GF(2^n)
48
+ * Goppa: a class for encoding and decoding Goppa codes
47
49
 
48
50
  * BlockCipher: a class implementing the usual modes of operation (ECB, CBC, GCM, etc.)
49
51
  * AESCipher: individual AES operations
@@ -6,6 +6,7 @@ kryptools/Zmod.py
6
6
  kryptools/__init__.py
7
7
  kryptools/aes.py
8
8
  kryptools/blockcipher.py
9
+ kryptools/code.py
9
10
  kryptools/conway_polynomials.py
10
11
  kryptools/des.py
11
12
  kryptools/dlp.py
@@ -36,6 +37,7 @@ kryptools.egg-info/top_level.txt
36
37
  tests/test_GF2.py
37
38
  tests/test_Zmod.py
38
39
  tests/test_aes.py
40
+ tests/test_code.py
39
41
  tests/test_des.py
40
42
  tests/test_dlog.py
41
43
  tests/test_ec.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "1.2"
3
+ version = "1.3"
4
4
  authors = [
5
5
  { name="Gerald Teschl", email="gerald.teschl@univie.ac.at" },
6
6
  ]
@@ -0,0 +1,32 @@
1
+ import pytest
2
+ from random import randint, seed
3
+ from kryptools import Zmod, GF2, Poly, Matrix
4
+ from kryptools import gen2pchk, Goppa
5
+
6
+ seed(0)
7
+ Z_2 = Zmod(2)
8
+ G_Hamming = Matrix([
9
+ [1, 0, 0, 0, 1, 1, 0],
10
+ [0, 1, 0, 0, 1, 0, 1],
11
+ [0, 0, 1, 0, 0, 1, 1],
12
+ [0, 0, 0, 1, 1, 1, 1]
13
+ ], ring = Z_2)
14
+
15
+
16
+ def test_gen2pchk():
17
+ H = gen2pchk(G_Hamming)
18
+ assert not H * G_Hamming.transpose()
19
+
20
+ def test_Goppa():
21
+ gf = GF2(4)
22
+ g = Poly([2, 0, 0, 1], ring = gf)
23
+ alpha = list(gf)
24
+
25
+ goppa = Goppa(gf, g, alpha)
26
+ for _ in range(10):
27
+ x = [ randint(0,1) for _ in range(goppa.G.rows) ]
28
+ y = goppa.encode(x)
29
+ for _ in range(3):
30
+ i = randint(0, goppa.G.cols-1)
31
+ y[i] = 1- y[i]
32
+ assert goppa.decode(y) == x
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
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