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.
- {kryptools-1.3 → kryptools-1.3.2}/PKG-INFO +1 -1
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/GF2.py +3 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/Zmod.py +13 -5
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/__init__.py +1 -1
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/code.py +33 -17
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/la.py +1 -1
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/poly.py +19 -7
- {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/PKG-INFO +1 -1
- {kryptools-1.3 → kryptools-1.3.2}/pyproject.toml +1 -1
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_GF2.py +5 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_Zmod.py +36 -5
- kryptools-1.3.2/tests/test_code.py +41 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_la.py +7 -0
- kryptools-1.3.2/tests/test_poly.py +36 -0
- kryptools-1.3/tests/test_code.py +0 -32
- kryptools-1.3/tests/test_poly.py +0 -20
- {kryptools-1.3 → kryptools-1.3.2}/LICENSE +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/README.md +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/aes.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/blockcipher.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/conway_polynomials.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/des.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_ic.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_qs.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/dlp_rho.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/ec.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_dix.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_ecm.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_fmt.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_pm1.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_qs.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/factor_rho.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/intfuncs.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/keccak.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/lat.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/nt.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/primes.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools/sha1.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/SOURCES.txt +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/setup.cfg +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_aes.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_des.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_dlog.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_ec.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor_fmt.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor_pm1.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_factor_qs.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_intfuncs.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_keccak.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_lat.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_nt.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_primes.py +0 -0
- {kryptools-1.3 → kryptools-1.3.2}/tests/test_sha1.py +0 -0
|
@@ -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(
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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)
|
|
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 <=
|
|
33
|
+
while j <= M.cols and not M[i, j]:
|
|
30
34
|
j += 1
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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] =
|
|
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
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
397
|
-
|
|
408
|
+
return True
|
|
409
|
+
|
|
@@ -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(
|
|
65
|
-
|
|
66
|
-
assert
|
|
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
|
kryptools-1.3/tests/test_code.py
DELETED
|
@@ -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
|
kryptools-1.3/tests/test_poly.py
DELETED
|
@@ -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
|
|
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
|