kryptools 1.3__tar.gz → 1.3.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 (59) hide show
  1. {kryptools-1.3 → kryptools-1.3.2}/PKG-INFO +1 -1
  2. {kryptools-1.3 → kryptools-1.3.2}/kryptools/GF2.py +3 -0
  3. {kryptools-1.3 → kryptools-1.3.2}/kryptools/Zmod.py +13 -5
  4. {kryptools-1.3 → kryptools-1.3.2}/kryptools/__init__.py +1 -1
  5. {kryptools-1.3 → kryptools-1.3.2}/kryptools/code.py +33 -17
  6. {kryptools-1.3 → kryptools-1.3.2}/kryptools/la.py +1 -1
  7. {kryptools-1.3 → kryptools-1.3.2}/kryptools/poly.py +19 -7
  8. {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/PKG-INFO +1 -1
  9. {kryptools-1.3 → kryptools-1.3.2}/pyproject.toml +1 -1
  10. {kryptools-1.3 → kryptools-1.3.2}/tests/test_GF2.py +5 -0
  11. {kryptools-1.3 → kryptools-1.3.2}/tests/test_Zmod.py +36 -5
  12. kryptools-1.3.2/tests/test_code.py +41 -0
  13. {kryptools-1.3 → kryptools-1.3.2}/tests/test_la.py +7 -0
  14. kryptools-1.3.2/tests/test_poly.py +36 -0
  15. kryptools-1.3/tests/test_code.py +0 -32
  16. kryptools-1.3/tests/test_poly.py +0 -20
  17. {kryptools-1.3 → kryptools-1.3.2}/LICENSE +0 -0
  18. {kryptools-1.3 → kryptools-1.3.2}/README.md +0 -0
  19. {kryptools-1.3 → kryptools-1.3.2}/kryptools/aes.py +0 -0
  20. {kryptools-1.3 → kryptools-1.3.2}/kryptools/blockcipher.py +0 -0
  21. {kryptools-1.3 → kryptools-1.3.2}/kryptools/conway_polynomials.py +0 -0
  22. {kryptools-1.3 → kryptools-1.3.2}/kryptools/des.py +0 -0
  23. {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp.py +0 -0
  24. {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_bsgs.py +0 -0
  25. {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_ic.py +0 -0
  26. {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_qs.py +0 -0
  27. {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_rho.py +0 -0
  28. {kryptools-1.3 → kryptools-1.3.2}/kryptools/ec.py +0 -0
  29. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor.py +0 -0
  30. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_dix.py +0 -0
  31. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_ecm.py +0 -0
  32. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_fmt.py +0 -0
  33. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_pm1.py +0 -0
  34. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_qs.py +0 -0
  35. {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_rho.py +0 -0
  36. {kryptools-1.3 → kryptools-1.3.2}/kryptools/intfuncs.py +0 -0
  37. {kryptools-1.3 → kryptools-1.3.2}/kryptools/keccak.py +0 -0
  38. {kryptools-1.3 → kryptools-1.3.2}/kryptools/lat.py +0 -0
  39. {kryptools-1.3 → kryptools-1.3.2}/kryptools/nt.py +0 -0
  40. {kryptools-1.3 → kryptools-1.3.2}/kryptools/primes.py +0 -0
  41. {kryptools-1.3 → kryptools-1.3.2}/kryptools/sha1.py +0 -0
  42. {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/SOURCES.txt +0 -0
  43. {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/dependency_links.txt +0 -0
  44. {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/top_level.txt +0 -0
  45. {kryptools-1.3 → kryptools-1.3.2}/setup.cfg +0 -0
  46. {kryptools-1.3 → kryptools-1.3.2}/tests/test_aes.py +0 -0
  47. {kryptools-1.3 → kryptools-1.3.2}/tests/test_des.py +0 -0
  48. {kryptools-1.3 → kryptools-1.3.2}/tests/test_dlog.py +0 -0
  49. {kryptools-1.3 → kryptools-1.3.2}/tests/test_ec.py +0 -0
  50. {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor.py +0 -0
  51. {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor_fmt.py +0 -0
  52. {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor_pm1.py +0 -0
  53. {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor_qs.py +0 -0
  54. {kryptools-1.3 → kryptools-1.3.2}/tests/test_intfuncs.py +0 -0
  55. {kryptools-1.3 → kryptools-1.3.2}/tests/test_keccak.py +0 -0
  56. {kryptools-1.3 → kryptools-1.3.2}/tests/test_lat.py +0 -0
  57. {kryptools-1.3 → kryptools-1.3.2}/tests/test_nt.py +0 -0
  58. {kryptools-1.3 → kryptools-1.3.2}/tests/test_primes.py +0 -0
  59. {kryptools-1.3 → kryptools-1.3.2}/tests/test_sha1.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryptools
3
- Version: 1.3
3
+ Version: 1.3.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
  License: MIT
@@ -62,6 +62,9 @@ class GF2:
62
62
  return [GF2nPoint(xx, self) for xx in x]
63
63
  return GF2nPoint(x, self)
64
64
 
65
+ def __len__(self):
66
+ return self.order
67
+
65
68
  def __iter__(self):
66
69
  for x in range(self.order):
67
70
  yield GF2nPoint(x, self)
@@ -98,6 +98,10 @@ class Zmod:
98
98
  "Return a generator of the group Z_n^*."
99
99
  if not self.is_cyclic():
100
100
  return None
101
+ if self.n == 1:
102
+ return self(0)
103
+ if self.n == 2:
104
+ return self(1)
101
105
  for a in range(2, self.n):
102
106
  if gcd(a, self.n) > 1:
103
107
  continue
@@ -109,17 +113,21 @@ class Zmod:
109
113
  "Return a generator for all generators of the group Z_n^*."
110
114
  a = self.generator()
111
115
  if a is not None:
116
+ yield a
112
117
  self.order()
113
- for j in range(1, self.group_order):
118
+ for j in range(2, self.group_order):
114
119
  if gcd(j, self.group_order) == 1:
115
120
  yield a**j
116
121
 
117
122
  def star(self) -> list:
118
123
  "Return a generator for all elements of the group Z_n^*."
119
- yield self(1)
120
- for a in range(2, self.n):
121
- if gcd(a, self.n) == 1:
122
- yield self(a)
124
+ if self.n == 1:
125
+ yield self(0)
126
+ else:
127
+ yield self(1)
128
+ for a in range(2, self.n):
129
+ if gcd(a, self.n) == 1:
130
+ yield self(a)
123
131
 
124
132
 
125
133
  class ZmodPoint:
@@ -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.3"
8
+ __version__ = "1.3.2"
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
@@ -17,31 +17,39 @@ def poly2bits(x: Poly) -> list:
17
17
 
18
18
  def left_standard_form(M: Matrix) -> (Matrix, Matrix):
19
19
  "Compute the left standard form of a generator matrix. Return the standard form and the pertmutation matrix."
20
+ # reduced row echelon form
20
21
  M = M.rref()
22
+ # purge zero rows
21
23
  for i in range(M.rows-1,-1,-1):
22
24
  if not M[i,:]:
23
- M.delete_rows(i) # remove zero rows
25
+ M.delete_rows(i)
26
+ # permute columns to get the identity on the left
24
27
  last = min(M.rows, M.cols)
25
28
  P = eye(M.cols)
26
29
  for i in range(last):
27
- if not M[i,i]:
30
+ if not M[i,i]: # the diagonal entry vanishes
31
+ # find the index of the pivot and permute
28
32
  j = i + 1
29
- while j <= last and not M[i, j]:
33
+ while j <= M.cols and not M[i, j]:
30
34
  j += 1
31
- if j <= last:
32
- P[:,i], P[:,j] = P[:,j], P[:,i]
33
- M[:,i], M[:,j] = M[:,j], M[:,i]
35
+ P[:,i], P[:,j] = P[:,j], P[:,i]
36
+ M[:,i], M[:,j] = M[:,j], M[:,i]
34
37
  return M, P
35
38
 
36
39
  def gen2pchk(G: Matrix) -> Matrix:
37
40
  "Compute the parity check matrix from a given generator matrix (and vice versa)."
38
41
  G, P = left_standard_form(G)
39
42
  d = G.cols - G.rows
40
- assert d > 0
43
+ if d <= 0:
44
+ raise ValueError("A generator matrix must have more columns than rows!")
41
45
  zero = 0 * G[0]
46
+ one = zero**0
47
+ # we start with a zero matrix
42
48
  H = zeros(d, G.cols, zero = zero)
49
+ # create the identity on the right
43
50
  for i in range(d):
44
- H[i,G.rows+i] = zero**0
51
+ H[i,G.rows+i] = one
52
+ # add minus the transpose of the right part of G as the left part
45
53
  tmp = - G[:,-d:].transpose()
46
54
  for i in range(G.cols - d):
47
55
  H[:, i] = tmp[:, i]
@@ -55,12 +63,12 @@ def hamming_dist(a: iter, b: iter):
55
63
 
56
64
  class Goppa():
57
65
  """
58
- Binary Goppa code.
66
+ Binary irreducible Goppa code.
59
67
 
60
68
  Example:
61
69
 
62
70
  >>> gf = GF2(4) # base field GF(2^n)
63
- >>> g = Poly([2, 0, 0, 1], ring = gf) # Polynomial for the code
71
+ >>> g = Poly([2, 0, 0, 1], ring = gf) # irreducible Polynomial for the code
64
72
  >>> alpha = list(gf) # list of points from the base field (must not contain zeros of g)
65
73
  >>> goppa = Goppa(gf, g, alpha)
66
74
 
@@ -68,17 +76,20 @@ class Goppa():
68
76
  >>> goppa.encode([1, 0, 1, 1])
69
77
  [0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1]
70
78
 
71
- Decoding still works if there are atmost deg(g) errors:
79
+ Decoding still works if there are at most deg(g) errors:
72
80
  >>> goppa.decode([0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0])
73
81
  [1, 0, 1, 1]
74
82
 
75
83
  """
76
84
 
77
85
  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
86
+ if not all(map(lambda x: x in gf, alpha)):
87
+ raise ValueError(f"{x}: alpha must be a list of elements from the Galois field!")
88
+ if not g.rabin_test():
89
+ raise ValueError(f"The polynomial g must be irreducible!")
90
+ self.gf = gf # underlying Galois field
91
+ self.g = g # polynomial
92
+ self.alpha = alpha # list of elements from gf
82
93
  # Compute the control matrix
83
94
  self.Z_2 = Zmod(2)
84
95
 
@@ -89,6 +100,9 @@ class Goppa():
89
100
  # Compute the generator matrix
90
101
  self.G = gen2pchk(self.H)
91
102
 
103
+ def __repr__(self):
104
+ return f"Binary irreducible Goppa code over GF(2^{self.gf.power}) with polynomial g(x) = {self.g}."
105
+
92
106
  def encode(self, x: list[int]):
93
107
  "Encode a given list of bits."
94
108
  x = Matrix(x, ring = self.Z_2)
@@ -109,16 +123,18 @@ class Goppa():
109
123
  v.modulus = None
110
124
  r0, r1 = self.g, v
111
125
  y0, y1 = Poly([self.gf(0)]), Poly([self.gf(1)])
112
- while r1 and 2* r1.degree() > self.g.degree():
126
+ while 2 * r1.degree() > self.g.degree():
113
127
  q, r = r0.divmod(r1)
114
128
  r0, r1 = r1, r
115
129
  y0, y1 = y1, y0 - q * y1
116
130
  a, b = r1, y1
117
131
  sigma = a**2 + b**2 * Poly([0,1], ring = self.gf)
118
132
  # correct the error
119
- for x in self.gf:
133
+ for x in self.alpha:
120
134
  if not sigma(x):
121
135
  y[int(x)] += 1
136
+ if self.H * y:
137
+ raise ValueError("Decoding failed!")
122
138
  x = self.G.transpose().solve(y)
123
139
  x.map(int)
124
140
  return list(x)
@@ -191,7 +191,7 @@ class Matrix:
191
191
  return False
192
192
  if self.rows != other.rows or self.cols != other.cols:
193
193
  return False
194
- return any(self[i] == other[i] for i in range(self.rows * self.cols))
194
+ return all(self[i] == other[i] for i in range(self.rows * self.cols))
195
195
 
196
196
  def __bool__(self):
197
197
  return any(bool(self[i]) for i in range(self.rows * self.cols))
@@ -4,7 +4,7 @@ Polynomials
4
4
 
5
5
  from numbers import Number
6
6
  from .primes import is_prime
7
- from .factor import factorint
7
+ #from .factor import factorint
8
8
 
9
9
  class Poly:
10
10
  """
@@ -387,11 +387,23 @@ class Poly:
387
387
  isfield = True
388
388
  if not isfield:
389
389
  raise ValueError("The polynomial does not seem to be over a finite field.")
390
- n = self.degree()
391
- x = self.__class__([0, 1], ring=ring, modulus = self.coeff) # x
392
- for p in factorint(n).keys():
393
- g = self.gcd(x**(q**(n//p)) - x) # gcd with x^{q/n} - x
390
+ #n = self.degree()
391
+ #x = self.__class__([0, 1], ring=ring, modulus = self.coeff) # x
392
+ #for p in factorint(n).keys():
393
+ # g = self.gcd(x**(q**(n//p)) - x) # gcd with x^{q/n} - x
394
+ # if g.degree():
395
+ # return False
396
+ #g = x**(q**n) - x
397
+ #return not(g)
398
+ x = Poly([0, 1], ring = ring) # x
399
+ xq = Poly(q * [0] + [1], ring = ring, modulus = self.coeff) # x^q modulo self to keep the polynomials small
400
+ for k in range(1, self.degree() // 2 + 1):
401
+ if k == 1:
402
+ b = xq
403
+ else:
404
+ b **= q # we compute x^{q^k} mod a recursively
405
+ g = self.gcd(b - x) # gcd with x^{q^k} - x
394
406
  if g.degree():
395
407
  return False
396
- g = x**(q**n) - x
397
- return not(g)
408
+ return True
409
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryptools
3
- Version: 1.3
3
+ Version: 1.3.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
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "1.3"
3
+ version = "1.3.2"
4
4
  authors = [
5
5
  { name="Gerald Teschl", email="gerald.teschl@univie.ac.at" },
6
6
  ]
@@ -8,6 +8,11 @@ num_tests = 50
8
8
  def test_GF2_ops():
9
9
  for n, modulus in [(4, None), (8, None), (8, 0b100011011), (12, None), (128, 0b11100001 << 120)]:
10
10
  gf = GF2(n, modulus=modulus)
11
+ assert gf(1)
12
+ assert not gf(0)
13
+ assert gf(1) == gf(1)
14
+ assert not gf(1) == gf(0)
15
+ assert not gf(0) == 0
11
16
  if gf.power < 17:
12
17
  assert len(list(gf)) == gf.order
13
18
  assert len(list(gf.star())) == gf.order - 1
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
  from math import gcd
3
- from kryptools import Zmod, euler_phi
3
+ from kryptools import Zmod, euler_phi, is_prime
4
4
 
5
5
 
6
6
  def test_Zmod_ops():
@@ -42,6 +42,11 @@ def test_Zmod_methods():
42
42
  assert list(Z_5.star()) == Z_5([1, 2, 3, 4])
43
43
  assert [Z_5(i).sharp() for i in range(Z_5.n)] == [0, 1, 2, -2, -1]
44
44
  assert [abs(Z_5(i)) for i in range(Z_5.n)] == [0, 1, 2, 2, 1]
45
+ assert not Z_5(0)
46
+ assert Z_5(1)
47
+ assert Z_5(2) == Z_5(2)
48
+ assert Z_5(2) != Z_5(3)
49
+ assert Z_5(2) != 2
45
50
  assert str(Z_5(3)) == "3"
46
51
  Z_5.short = False
47
52
  assert str(Z_5(6)) == "1 (mod 5)"
@@ -57,13 +62,22 @@ def test_Zmod_methods():
57
62
  assert Z_6(5).is_generator() is True
58
63
  assert list(Z_6.generators()) == Z_6([5])
59
64
  assert list(Z_6.star()) == Z_6([1, 5])
65
+ assert Z_6(1)
66
+ assert Z_6(2) == Z_6(2)
67
+ assert Z_6(2) != Z_6(3)
68
+ assert Z_5(2) != Z_6(2)
60
69
  assert str(Z_6(3)) == "3"
61
70
 
62
71
 
63
72
  def test_Zmod_order():
64
- for n in range(2, 10):
65
- Z_n = Zmod(n)
66
- assert Z_n.order() == euler_phi(n)
73
+ for n in range(1, 100):
74
+ o = euler_phi(n)
75
+ assert Zmod(n).order() == o
76
+ assert len(list(Zmod(n).star())) == o
77
+
78
+ def test_Zmod_field():
79
+ for n in range(1, 100):
80
+ assert Zmod(n).is_field() == is_prime(n)
67
81
 
68
82
 
69
83
  OEIS_A033948 = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 13, 14, 17, 18, 19, 22, 23, 25, 26, 27,
@@ -71,7 +85,24 @@ OEIS_A033948 = [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 13, 14, 17, 18, 19, 22, 23, 25,
71
85
  79, 81, 82, 83, 86, 89, 94, 97, 98, 101, 103, 106, 107, 109, 113, 118, 121, 122, 125,
72
86
  127, 131, 134, 137, 139]
73
87
 
74
-
75
88
  def test_Zmod_cyclic():
76
89
  for n in range(2, OEIS_A033948[-1]+1):
77
90
  assert Zmod(n).is_cyclic() == (n in OEIS_A033948)
91
+
92
+ OEIS_A046145 = [0, 1, 2, 3, 2, 5, 3, 0, 2, 3, 2, 0, 2, 3, 0, 0, 3, 5, 2, 0, 0, 7, 5, 0, 2, 7, 2, 0, 2, 0, 3, 0, 0, 3, 0,
93
+ 0, 2, 3, 0, 0, 6, 0, 3, 0, 0, 5, 5, 0, 3, 3, 0, 0, 2, 5, 0, 0, 0, 3, 2, 0, 2, 3, 0, 0, 0, 0, 2, 0, 0, 0,
94
+ 7, 0, 5, 5, 0, 0, 0, 0, 3, 0, 2, 7, 2, 0, 0, 3, 0, 0, 3, 0]
95
+
96
+ def test_Zmod_generator():
97
+ for j, a in enumerate(OEIS_A046145):
98
+ aa = Zmod(j+1).generator()
99
+ if aa is None:
100
+ aa = 0
101
+ assert a == int(aa)
102
+
103
+ def test_Zmod_generators():
104
+ for n in range(1, 100):
105
+ if Zmod(n).is_cyclic():
106
+ assert len(list(Zmod(n).generators())) == euler_phi(euler_phi(n))
107
+ else:
108
+ assert list(Zmod(n).generators()) == []
@@ -0,0 +1,41 @@
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
+
9
+ def Hamming2(h: int) -> Matrix:
10
+ "Parity check matrix for the binary Hamming code."
11
+ out = []
12
+ for i in range(1,2**h):
13
+ out.append([int(d) for d in str(format(i, "0" + str(h) + "b"))])
14
+ return Matrix(out, ring = Z_2).transpose()
15
+
16
+
17
+ def test_gen2pchk():
18
+ for h in range(2,6):
19
+ H = Hamming2(h)
20
+ G = gen2pchk(H)
21
+ assert not H * G.transpose()
22
+
23
+ num_tests = 10
24
+
25
+ def test_Goppa():
26
+ for gf, t in [ [GF2(4), 3], [GF2(6), 4]]:
27
+ found = False
28
+ while not found:
29
+ c = [randint(0,gf.order-1) for _ in range(t)] + [1]
30
+ g = Poly(c, ring = gf)
31
+ found = g.rabin_test()
32
+ alpha = list(gf)
33
+
34
+ goppa = Goppa(gf, g, alpha)
35
+ for _ in range(num_tests):
36
+ x = [ randint(0,1) for _ in range(goppa.G.rows) ]
37
+ y = goppa.encode(x)
38
+ for _ in range(t):
39
+ i = randint(0, goppa.G.cols-1)
40
+ y[i] = 1- y[i]
41
+ assert goppa.decode(y) == x
@@ -5,6 +5,13 @@ from kryptools import Matrix, Zmod
5
5
 
6
6
  def test_Matrix():
7
7
  M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 12]])
8
+ Z = M.zeros()
9
+ assert M
10
+ assert M == M
11
+ assert not Z
12
+ Z[0] = 1
13
+ assert Z
14
+ assert Z != Z.zeros()
8
15
  assert len(M) == 3 * 3
9
16
  assert M[0] == 1
10
17
  assert M[:] == [1, 2, 3, 4, 5, 6, 7, 8, 12]
@@ -0,0 +1,36 @@
1
+ import pytest
2
+ from kryptools import Poly, Zmod, GF2
3
+ from kryptools import divisors, moebius_mu
4
+
5
+
6
+ def test_Poly():
7
+ p = Poly([2, 0, 2])
8
+ q = Poly([1, 2, 3, 4])
9
+ d, m = q.divmod(p)
10
+ assert d * p + m == q
11
+
12
+ Z_5 = Zmod(5)
13
+ p.map(Z_5)
14
+ q.map(Z_5)
15
+ d, m = q.divmod(p)
16
+ assert d * p + m == q
17
+
18
+ gf = GF2(8, modulus=0b100011011)
19
+ p = Poly([2, 1, 1, 3], modulus=[1, 0, 0, 0, 1], ring=gf)
20
+ q = p.inv()
21
+ assert p * q == Poly([1], modulus=[1, 0, 0, 0, 1], ring=gf)
22
+
23
+ def test_rabin():
24
+ for gf,t in [ [Zmod(7), 4], [GF2(4), 3]]:
25
+ order = len(list(gf))
26
+ count = 0
27
+ for i in range(order**t):
28
+ c = []
29
+ while i:
30
+ i, m = divmod(i, order)
31
+ c.append(m)
32
+ c += [0] * (t- len(c)) + [1]
33
+ a = Poly(c, ring=gf)
34
+ if a.rabin_test():
35
+ count += 1
36
+ assert count == sum([moebius_mu(d) * order ** (t // d) for d in divisors(t)]) // t
@@ -1,32 +0,0 @@
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
@@ -1,20 +0,0 @@
1
- import pytest
2
- from kryptools import Poly, Zmod, GF2
3
-
4
-
5
- def test_Poly():
6
- p = Poly([2, 0, 2])
7
- q = Poly([1, 2, 3, 4])
8
- d, m = q.divmod(p)
9
- assert d * p + m == q
10
-
11
- Z_5 = Zmod(5)
12
- p.map(Z_5)
13
- q.map(Z_5)
14
- d, m = q.divmod(p)
15
- assert d * p + m == q
16
-
17
- gf = GF2(8, modulus=0b100011011)
18
- p = Poly([2, 1, 1, 3], modulus=[1, 0, 0, 0, 1], ring=gf)
19
- q = p.inv()
20
- assert p * q == Poly([1], modulus=[1, 0, 0, 0, 1], ring=gf)
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