kryptools 1.0__tar.gz → 1.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-1.0 → kryptools-1.0.2}/PKG-INFO +3 -2
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/GF2.py +2 -2
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/__init__.py +2 -2
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/aes.py +2 -1
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/blockcipher.py +14 -15
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/des.py +34 -9
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor_pm1.py +1 -1
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/la.py +2 -1
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/nt.py +1 -1
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/poly.py +1 -2
- {kryptools-1.0 → kryptools-1.0.2}/kryptools.egg-info/PKG-INFO +3 -2
- {kryptools-1.0 → kryptools-1.0.2}/pyproject.toml +1 -1
- kryptools-1.0.2/tests/test_des.py +59 -0
- kryptools-1.0/tests/test_des.py +0 -42
- {kryptools-1.0 → kryptools-1.0.2}/LICENSE +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/README.md +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/Zmod.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/conway_polynomials.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/dlp.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/dlp_bsgs.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/dlp_ic.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/dlp_qs.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/dlp_rho.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/ec.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor_dix.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor_ecm.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor_fmt.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor_qs.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/factor_rho.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/intfuncs.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/lat.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools/primes.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools.egg-info/SOURCES.txt +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools.egg-info/dependency_links.txt +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/kryptools.egg-info/top_level.txt +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/setup.cfg +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_GF2.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_Zmod.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_aes.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_dlog.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_ec.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_factor.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_factor_fmt.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_factor_pm1.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_factor_qs.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_intfuncs.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_la.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_lat.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_nt.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_poly.py +0 -0
- {kryptools-1.0 → kryptools-1.0.2}/tests/test_primes.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kryptools
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.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
|
License: MIT
|
|
@@ -14,6 +14,7 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Requires-Python: >=3.10
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
17
18
|
|
|
18
19
|
# kryptools
|
|
19
20
|
Gerald Teschl <Gerald.Teschl@univie.ac.at>
|
|
@@ -234,6 +234,7 @@ class GF2_aes(GF_2):
|
|
|
234
234
|
order: int = 256 # 2**n
|
|
235
235
|
|
|
236
236
|
def sbox(self, inv: bool = False) -> "GF2_aes":
|
|
237
|
+
"Apply the AES sbox."
|
|
237
238
|
if inv:
|
|
238
239
|
return aes_sbox_inv[self.x]
|
|
239
240
|
return aes_sbox[self.x]
|
|
@@ -260,6 +261,7 @@ class GF2_miniaes(GF_2):
|
|
|
260
261
|
order: int = 16 # 2**n
|
|
261
262
|
|
|
262
263
|
def sbox(self, inv: bool = False) -> "GF2_miniaes":
|
|
264
|
+
"Apply the Mini-AES sbox."
|
|
263
265
|
if inv:
|
|
264
266
|
return miniaes_sbox_inv[self.x]
|
|
265
267
|
return miniaes_sbox[self.x]
|
|
@@ -277,5 +279,3 @@ class GF2_ghash(GF_2):
|
|
|
277
279
|
power: int = 128 # n
|
|
278
280
|
order: int = 2**128 # 2**n
|
|
279
281
|
bitreversed: bool = True
|
|
280
|
-
|
|
281
|
-
|
|
@@ -5,7 +5,7 @@ Implemenation of same basic algorithms used in cryptography.
|
|
|
5
5
|
__author__ = "Gerald Teschl"
|
|
6
6
|
__copyright__ = "Copyright 2024, Gerald Teschl"
|
|
7
7
|
__license__ = "MIT License"
|
|
8
|
-
__version__ = "0.
|
|
8
|
+
__version__ = "1.0.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
|
|
@@ -21,4 +21,4 @@ from .Zmod import Zmod
|
|
|
21
21
|
from .GF2 import GF2, GF2_aes, GF2_miniaes, GF2_ghash
|
|
22
22
|
from .blockcipher import BlockCipher, bytexor
|
|
23
23
|
from .aes import AESKeySchedule, AESCipher, AESBlockCipher
|
|
24
|
-
from .des import list2int, SDESKeySchedule, SDESCipher, DESKeySchedule, DESCipher, DESBlockCipher
|
|
24
|
+
from .des import list2int, int2list, permute, invert_permutation, rotate_left, SDESKeySchedule, SDESCipher, DESKeySchedule, DESCipher, DESBlockCipher
|
|
@@ -137,7 +137,7 @@ class AESKeySchedule:
|
|
|
137
137
|
for j in range(4):
|
|
138
138
|
tmp.append(int(self.key[j, i]))
|
|
139
139
|
return bytes(tmp)
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
def next(self) -> None:
|
|
142
142
|
"Apply one round of the key shedule and return the next key."
|
|
143
143
|
self.round += 1
|
|
@@ -169,6 +169,7 @@ class AESKeySchedule:
|
|
|
169
169
|
return keys
|
|
170
170
|
|
|
171
171
|
class AESBlockCipher(BlockCipher):
|
|
172
|
+
"Block cipher class for AES"
|
|
172
173
|
blocksize = 16
|
|
173
174
|
def set_key(self, key: bytes):
|
|
174
175
|
if not isinstance(key, bytes) and len(key) != self.__class__.blocksize:
|
|
@@ -10,9 +10,9 @@ def bytexor(a: bytes, b: bytes) -> bytes:
|
|
|
10
10
|
|
|
11
11
|
class BlockCipher:
|
|
12
12
|
"Generic class for a block cipher."
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
blocksize: int = 1 # blocksize in bytes
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def __init__(self, key: bytes|int = None, mode: str|None = None):
|
|
17
17
|
self.key = None # here we store the key (if any)
|
|
18
18
|
self.cipher = None # here we can store an instance of the cipher initialized with the key
|
|
@@ -53,7 +53,7 @@ class BlockCipher:
|
|
|
53
53
|
try:
|
|
54
54
|
method = getattr(self, "encrypt_" + mode.lower())
|
|
55
55
|
except:
|
|
56
|
-
raise ValueError("Unsupported encryption mode: ",mode
|
|
56
|
+
raise ValueError("Unsupported encryption mode: ", mode)
|
|
57
57
|
if key:
|
|
58
58
|
self.set_key(key)
|
|
59
59
|
return method(text)
|
|
@@ -65,7 +65,7 @@ class BlockCipher:
|
|
|
65
65
|
try:
|
|
66
66
|
method = getattr(self, "decrypt_" + mode)
|
|
67
67
|
except:
|
|
68
|
-
raise ValueError("Unsupported encryption mode: ",mode)
|
|
68
|
+
raise ValueError("Unsupported encryption mode: ", mode)
|
|
69
69
|
if key:
|
|
70
70
|
self.set_key(key)
|
|
71
71
|
return method(ctext)
|
|
@@ -89,7 +89,7 @@ class BlockCipher:
|
|
|
89
89
|
def encrypt_cbc(self, text: bytes, iv: bytes | None = None, padding: bool = True) -> bytes:
|
|
90
90
|
"Encrypt using CBC mode."
|
|
91
91
|
ctext = bytearray(b'')
|
|
92
|
-
if iv
|
|
92
|
+
if iv is None:
|
|
93
93
|
bb = randbytes(self.__class__.blocksize) # iv
|
|
94
94
|
else:
|
|
95
95
|
bb = iv
|
|
@@ -114,7 +114,7 @@ class BlockCipher:
|
|
|
114
114
|
def encrypt_cfb(self, text: bytes, iv: bytes | None = None) -> bytes:
|
|
115
115
|
"Encrypt using CFB mode."
|
|
116
116
|
ctext = bytearray(b'')
|
|
117
|
-
if iv
|
|
117
|
+
if iv is None:
|
|
118
118
|
bb = randbytes(self.__class__.blocksize) # iv
|
|
119
119
|
else:
|
|
120
120
|
bb = iv
|
|
@@ -139,7 +139,7 @@ class BlockCipher:
|
|
|
139
139
|
def encrypt_ofb(self, text: bytes, iv: bytes | None = None) -> bytes:
|
|
140
140
|
"Encrypt using OFB mode."
|
|
141
141
|
ctext = bytearray(b'')
|
|
142
|
-
if iv
|
|
142
|
+
if iv is None:
|
|
143
143
|
z = randbytes(self.__class__.blocksize) # iv
|
|
144
144
|
else:
|
|
145
145
|
z = iv
|
|
@@ -156,7 +156,7 @@ class BlockCipher:
|
|
|
156
156
|
ctext = ctext[self.__class__.blocksize:] # remove iv
|
|
157
157
|
for b in self.blocksplit(ctext, False):
|
|
158
158
|
z = self.encrypt_block(z)
|
|
159
|
-
text.extend(bytexor(b, z))
|
|
159
|
+
text.extend(bytexor(b, z))
|
|
160
160
|
return bytes(text)
|
|
161
161
|
|
|
162
162
|
def adv_ctr(self, z: bytes, s: int) -> bytes:
|
|
@@ -164,17 +164,16 @@ class BlockCipher:
|
|
|
164
164
|
zz = bytearray(z)
|
|
165
165
|
for i in range(self.__class__.blocksize-1, self.__class__.blocksize-s-1, -1):
|
|
166
166
|
c = z[i]+1
|
|
167
|
-
if
|
|
167
|
+
if c < 256:
|
|
168
168
|
zz[i] = c
|
|
169
169
|
break
|
|
170
|
-
|
|
171
|
-
zz[i] = 0
|
|
170
|
+
zz[i] = 0
|
|
172
171
|
return zz
|
|
173
172
|
|
|
174
173
|
def encrypt_ctr(self, text: bytes, iv: bytes | None = None) -> bytes:
|
|
175
174
|
"Encrypt using CTR mode."
|
|
176
175
|
ctext = bytearray(b'')
|
|
177
|
-
if iv
|
|
176
|
+
if iv is None:
|
|
178
177
|
ctr = randbytes(self.__class__.blocksize) # iv
|
|
179
178
|
else:
|
|
180
179
|
ctr = iv
|
|
@@ -281,14 +280,14 @@ class BlockCipher:
|
|
|
281
280
|
len_block = b'\x00' * (self.__class__.blocksize // 2) + len_block
|
|
282
281
|
tag = 0
|
|
283
282
|
return h, len_block, tag
|
|
284
|
-
|
|
285
|
-
|
|
283
|
+
|
|
284
|
+
|
|
286
285
|
def encrypt_gcm(self, text: bytes, iv: bytes | None = None, aad: bytes | None = None) -> bytes:
|
|
287
286
|
"Encrypt using Galois CTR mode."
|
|
288
287
|
assert self.__class__.blocksize == 16, "GHASH requires a blocksize of 16 bytes."
|
|
289
288
|
ctext = bytearray(b'')
|
|
290
289
|
len_ctr = self.__class__.blocksize // 4
|
|
291
|
-
if iv
|
|
290
|
+
if iv is None:
|
|
292
291
|
iv = randbytes(self.__class__.blocksize - len_ctr)
|
|
293
292
|
else:
|
|
294
293
|
assert len(iv) + \
|
|
@@ -6,15 +6,29 @@ from math import ceil
|
|
|
6
6
|
from .blockcipher import BlockCipher
|
|
7
7
|
|
|
8
8
|
def permute(a: list[int], permutation: tuple[int]) -> list[int]:
|
|
9
|
-
"Apply a permutation to a list"
|
|
9
|
+
"Apply a permutation (DES style - counting starts at 1) to a list."
|
|
10
10
|
return [ a[i-1] for i in permutation]
|
|
11
11
|
|
|
12
|
+
def invert_permutation(permutation: tuple[int]) -> tuple[int]:
|
|
13
|
+
"Invert a permutation (DES style - counting starts at 1)."
|
|
14
|
+
inverse = [ 0 ] * len(permutation)
|
|
15
|
+
for i, j in enumerate(permutation):
|
|
16
|
+
inverse[j-1] = i+1
|
|
17
|
+
return tuple(inverse)
|
|
18
|
+
|
|
12
19
|
def rotate_left(l: list, n: int = 1) -> list:
|
|
13
20
|
"Rotate a list cyclically n places to the left."
|
|
14
21
|
n = n % len(l)
|
|
15
22
|
return l[n:] + l[:n]
|
|
16
23
|
|
|
24
|
+
def int2list(x: int, length: int = 8) -> list:
|
|
25
|
+
"Convert an integer or character to a list of binary digits."
|
|
26
|
+
if not isinstance(x, int):
|
|
27
|
+
x = ord(x)
|
|
28
|
+
return [int(d) for d in str(format(x, "0" + str(length) + "b"))]
|
|
29
|
+
|
|
17
30
|
def list2int(a: list) -> int:
|
|
31
|
+
"Convert a list of binary digits to an integer."
|
|
18
32
|
s = 0
|
|
19
33
|
for i, d in enumerate(reversed(a)):
|
|
20
34
|
if d:
|
|
@@ -48,7 +62,7 @@ class FeistelKeySchedule:
|
|
|
48
62
|
|
|
49
63
|
def __repr__(self):
|
|
50
64
|
if self.__class__.print_hex:
|
|
51
|
-
|
|
65
|
+
return str(format(int(self), "0" + str(ceil(self.keylength/4)) + "x"))
|
|
52
66
|
return str(self.state)
|
|
53
67
|
|
|
54
68
|
def __int__(self):
|
|
@@ -68,7 +82,7 @@ class FeistelKeySchedule:
|
|
|
68
82
|
|
|
69
83
|
def reset(self) -> None:
|
|
70
84
|
"Reset key schedule."
|
|
71
|
-
self.state =
|
|
85
|
+
self.state = permute(self.key, self.__class__.IP)
|
|
72
86
|
self.round = 0
|
|
73
87
|
|
|
74
88
|
def gen_keys(self) -> list:
|
|
@@ -79,7 +93,7 @@ class FeistelKeySchedule:
|
|
|
79
93
|
for _ in range(len(self.__class__.ROT)):
|
|
80
94
|
keys.append(self.next())
|
|
81
95
|
return keys
|
|
82
|
-
|
|
96
|
+
|
|
83
97
|
|
|
84
98
|
|
|
85
99
|
class FeistelCipher:
|
|
@@ -96,7 +110,7 @@ class FeistelCipher:
|
|
|
96
110
|
P_box: tuple = tuple() # permutation after sbox
|
|
97
111
|
S_split: tuple = tuple() # bit selection for sbox
|
|
98
112
|
S_box: tuple = tuple() # list of sboxes
|
|
99
|
-
|
|
113
|
+
|
|
100
114
|
def __init__(self, key: bytes = None):
|
|
101
115
|
self.keys = []
|
|
102
116
|
self.state = [ 0 ] * (self.__class__.blocksize * 8)
|
|
@@ -112,7 +126,7 @@ class FeistelCipher:
|
|
|
112
126
|
|
|
113
127
|
def __repr__(self):
|
|
114
128
|
if self.__class__.print_hex:
|
|
115
|
-
|
|
129
|
+
return str(format(int(self), "0" + str(self.__class__.blocksize * 2) + "x"))
|
|
116
130
|
s = ''
|
|
117
131
|
for i, d in enumerate(self.state):
|
|
118
132
|
if not i % 8 and 0 < i < self.__class__.blocksize * 8:
|
|
@@ -138,7 +152,7 @@ class FeistelCipher:
|
|
|
138
152
|
def xor(self, a: list[int], b: list[int]) -> list[int]:
|
|
139
153
|
"XOR two lists"
|
|
140
154
|
return [ i ^ j for i, j in zip(a,b)]
|
|
141
|
-
|
|
155
|
+
|
|
142
156
|
def left(self) -> list[int]:
|
|
143
157
|
"Left halve"
|
|
144
158
|
return self.state[:self.__class__.blocksize * 4]
|
|
@@ -151,10 +165,18 @@ class FeistelCipher:
|
|
|
151
165
|
"Switch left and right halves"
|
|
152
166
|
self.state = self.right() + self.left()
|
|
153
167
|
|
|
154
|
-
def f_box(self, a: list[int], key: list[int]) -> list[int]:
|
|
168
|
+
def f_box(self, a: list[int], key: list[int], showtmp:bool = False) -> list[int]:
|
|
155
169
|
"Nonlinear f-box"
|
|
170
|
+
if showtmp:
|
|
171
|
+
def printtmp(title:str, a: list) -> None:
|
|
172
|
+
print(f'{title}: {"".join(map(str,a))}')
|
|
173
|
+
else:
|
|
174
|
+
def printtmp(title:str, a: list) -> None:
|
|
175
|
+
pass
|
|
156
176
|
a = permute(a, self.__class__.E_box) # expansion box
|
|
177
|
+
printtmp("EBox", a)
|
|
157
178
|
a = self.xor(a, key) # add key
|
|
179
|
+
printtmp("XKey", a)
|
|
158
180
|
split = len(self.__class__.S_split)
|
|
159
181
|
# apply sboxes
|
|
160
182
|
num_sbox = len(self.__class__.S_box) # number of sboxes
|
|
@@ -168,7 +190,9 @@ class FeistelCipher:
|
|
|
168
190
|
s = self.__class__.S_box[i][index]
|
|
169
191
|
aa += [int(d) for d in str(format(s, "0" + str(out_len) + "b"))]
|
|
170
192
|
a = aa
|
|
193
|
+
printtmp("SBox", a)
|
|
171
194
|
a = permute(a, self.__class__.P_box) # permutation box
|
|
195
|
+
printtmp("PBox", a)
|
|
172
196
|
return a
|
|
173
197
|
|
|
174
198
|
def ip(self) -> None:
|
|
@@ -298,7 +322,7 @@ class DESCipher(FeistelCipher):
|
|
|
298
322
|
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
|
299
323
|
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
|
300
324
|
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13),
|
|
301
|
-
(15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5,
|
|
325
|
+
(15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
|
302
326
|
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
|
303
327
|
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
|
304
328
|
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9),
|
|
@@ -330,6 +354,7 @@ class DESCipher(FeistelCipher):
|
|
|
330
354
|
|
|
331
355
|
|
|
332
356
|
class DESBlockCipher(BlockCipher):
|
|
357
|
+
"Block cipher class for DES"
|
|
333
358
|
blocksize = 8
|
|
334
359
|
def set_key(self, key: bytes):
|
|
335
360
|
if not isinstance(key, bytes) and len(key) != self.__class__.blocksize:
|
|
@@ -47,7 +47,7 @@ def factor_pm1(n: int, B1: int | None = None, B2: int | None = None, x: int = 2,
|
|
|
47
47
|
g = gcd(x - 1, n)
|
|
48
48
|
if g == n: # we hit a multiple of n
|
|
49
49
|
if verbose:
|
|
50
|
-
|
|
50
|
+
print("\nFailed after stage one.")
|
|
51
51
|
return None
|
|
52
52
|
if 1 < g:
|
|
53
53
|
if verbose > 1:
|
|
@@ -51,6 +51,7 @@ class Matrix:
|
|
|
51
51
|
return '\n'.join(out)
|
|
52
52
|
|
|
53
53
|
def latex(self) -> str:
|
|
54
|
+
"Produce LaTeX code for the matrix."
|
|
54
55
|
res = "\\begin{pmatrix}\n"
|
|
55
56
|
for row in self.matrix:
|
|
56
57
|
res += " & ".join(map(str, row)) + '\\\\\n'
|
|
@@ -214,7 +215,7 @@ class Matrix:
|
|
|
214
215
|
|
|
215
216
|
def rref(self) -> "Matrix":
|
|
216
217
|
"Compute the reduced echelon form of a matrix M."
|
|
217
|
-
|
|
218
|
+
one = self._guess_zero()[1]
|
|
218
219
|
n, m = self.cols, self.rows
|
|
219
220
|
R = self[:, :]
|
|
220
221
|
i = 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kryptools
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.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
|
License: MIT
|
|
@@ -14,6 +14,7 @@ Classifier: Operating System :: OS Independent
|
|
|
14
14
|
Requires-Python: >=3.10
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
|
+
Dynamic: license-file
|
|
17
18
|
|
|
18
19
|
# kryptools
|
|
19
20
|
Gerald Teschl <Gerald.Teschl@univie.ac.at>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from kryptools import SDESKeySchedule, SDESCipher, DESKeySchedule, DESCipher, list2int
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_SDES():
|
|
6
|
+
# Test the key schedule
|
|
7
|
+
key = 34
|
|
8
|
+
test_values = [[0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0]]
|
|
9
|
+
|
|
10
|
+
ks = SDESKeySchedule(key)
|
|
11
|
+
assert ks.gen_keys() == test_values
|
|
12
|
+
|
|
13
|
+
# Test the encryption
|
|
14
|
+
x = b'\x01'
|
|
15
|
+
y = b'\xb9'
|
|
16
|
+
|
|
17
|
+
sdes = SDESCipher(key)
|
|
18
|
+
sdes(x).encrypt()
|
|
19
|
+
assert bytes(sdes) == y
|
|
20
|
+
assert sdes.decrypt() == x
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_DES():
|
|
24
|
+
# Test the key schedule
|
|
25
|
+
key = 0x0123456789ABCDEF.to_bytes(8, 'big')
|
|
26
|
+
test_values = [0x0B02679B49A5, 0x69A659256A26, 0x45D48AB428D2, 0x7289D2A58257, 0x3CE80317A6C2, 0x23251E3C8545, 0x6C04950AE4C6, 0x5788386CE581,
|
|
27
|
+
0xC0C9E926B839, 0x91E307631D72, 0x211F830D893A, 0x7130E5455C54, 0x91C4D04980FC, 0x5443B681DC8D, 0xB691050A16B5, 0xCA3D03B87032]
|
|
28
|
+
|
|
29
|
+
ks = DESKeySchedule(key)
|
|
30
|
+
keys = ks.gen_keys()
|
|
31
|
+
for k1, k2 in zip(keys, test_values):
|
|
32
|
+
assert list2int(k1) == k2
|
|
33
|
+
|
|
34
|
+
# Test the encryption (Handbook of Applied Cryptography and NBS Special Publication 500-20)
|
|
35
|
+
test_values = [[ 0x0123456789ABCDEF, 0x4E6F772069732074, 0x3FA40E8A984D4815 ],
|
|
36
|
+
[0x10316E028C8F3B4A, 0x0000000000000000, 0x82DCBAFBDEAB6602],
|
|
37
|
+
[0x0101010101010101, 0x95F8A5E5DD31D900, 0x8000000000000000],
|
|
38
|
+
[0x0101010101010101, 0xDD7F121CA5015619, 0x4000000000000000],
|
|
39
|
+
[0x0101010101010101, 0x2E8653104F3834EA, 0x2000000000000000],
|
|
40
|
+
[0x0101010101010101, 0x4BD388FF6CD81D4F, 0x1000000000000000],
|
|
41
|
+
[0x0101010101010101, 0x20B9E767B2FB1456, 0x0800000000000000],
|
|
42
|
+
[0x0101010101010101, 0x8000000000000000, 0x95F8A5E5DD31D900],
|
|
43
|
+
[0x0101010101010101, 0x4000000000000000, 0xDD7F121CA5015619],
|
|
44
|
+
[0x0101010101010101, 0x2000000000000000, 0x2E8653104F3834EA],
|
|
45
|
+
[0x0101010101010101, 0x1000000000000000, 0x4BD388FF6CD81D4F],
|
|
46
|
+
[0x8001010101010101, 0x0000000000000000, 0x95A8D72813DAA94D],
|
|
47
|
+
[0x4001010101010101, 0x0000000000000000, 0x0EEC1487DD8C26D5],
|
|
48
|
+
[0x2001010101010101, 0x0000000000000000, 0x7AD16FFB79C45926],
|
|
49
|
+
[0x1001010101010101, 0x0000000000000000, 0xD3746294CA6A6CF3]]
|
|
50
|
+
|
|
51
|
+
for key, x, y in test_values:
|
|
52
|
+
key = key.to_bytes(8, 'big')
|
|
53
|
+
x = x.to_bytes(8, 'big')
|
|
54
|
+
y = y.to_bytes(8, 'big')
|
|
55
|
+
|
|
56
|
+
des = DESCipher(key)
|
|
57
|
+
des(x).encrypt()
|
|
58
|
+
assert bytes(des) == y
|
|
59
|
+
assert des.decrypt() == x
|
kryptools-1.0/tests/test_des.py
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from kryptools import SDESKeySchedule, SDESCipher, DESKeySchedule, DESCipher, list2int
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def test_SDES():
|
|
6
|
-
# Test the key schedule
|
|
7
|
-
key = 34
|
|
8
|
-
test_values = [[0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 1, 0]]
|
|
9
|
-
|
|
10
|
-
ks = SDESKeySchedule(key)
|
|
11
|
-
assert ks.gen_keys() == test_values
|
|
12
|
-
|
|
13
|
-
# Test the encryption
|
|
14
|
-
x = b'\x01'
|
|
15
|
-
y = b'\xb9'
|
|
16
|
-
|
|
17
|
-
sdes = SDESCipher(key)
|
|
18
|
-
sdes(x).encrypt()
|
|
19
|
-
assert bytes(sdes) == y
|
|
20
|
-
assert sdes.decrypt() == x
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def test_DES():
|
|
24
|
-
# Test the key schedule
|
|
25
|
-
key = 0x0123456789ABCDEF.to_bytes(8, 'big')
|
|
26
|
-
test_values = [0x0B02679B49A5, 0x69A659256A26, 0x45D48AB428D2, 0x7289D2A58257, 0x3CE80317A6C2, 0x23251E3C8545, 0x6C04950AE4C6, 0x5788386CE581,
|
|
27
|
-
0xC0C9E926B839, 0x91E307631D72, 0x211F830D893A, 0x7130E5455C54, 0x91C4D04980FC, 0x5443B681DC8D, 0xB691050A16B5, 0xCA3D03B87032]
|
|
28
|
-
|
|
29
|
-
ks = DESKeySchedule(key)
|
|
30
|
-
keys = ks.gen_keys()
|
|
31
|
-
for k1, k2 in zip(keys, test_values):
|
|
32
|
-
assert list2int(k1) == k2
|
|
33
|
-
|
|
34
|
-
# Test the encryption (Handbook of Applied Cryptography)
|
|
35
|
-
key = 0x0123456789ABCDEF.to_bytes(8, 'big')
|
|
36
|
-
x = 0x4E6F772069732074.to_bytes(8, 'big')
|
|
37
|
-
y = 0x3FA40E8A984D4815.to_bytes(8, 'big')
|
|
38
|
-
|
|
39
|
-
des = DESCipher(key)
|
|
40
|
-
des(x).encrypt()
|
|
41
|
-
assert bytes(des) == y
|
|
42
|
-
assert des.decrypt() == 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
|