kryptools 1.0.2__tar.gz → 1.1__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 (55) hide show
  1. {kryptools-1.0.2 → kryptools-1.1}/PKG-INFO +6 -1
  2. {kryptools-1.0.2 → kryptools-1.1}/README.md +5 -0
  3. {kryptools-1.0.2 → kryptools-1.1}/kryptools/__init__.py +4 -2
  4. kryptools-1.1/kryptools/keccak.py +203 -0
  5. {kryptools-1.0.2 → kryptools-1.1}/kryptools/la.py +6 -0
  6. {kryptools-1.0.2 → kryptools-1.1}/kryptools/poly.py +9 -1
  7. kryptools-1.1/kryptools/sha1.py +86 -0
  8. {kryptools-1.0.2 → kryptools-1.1}/kryptools.egg-info/PKG-INFO +6 -1
  9. {kryptools-1.0.2 → kryptools-1.1}/kryptools.egg-info/SOURCES.txt +5 -1
  10. {kryptools-1.0.2 → kryptools-1.1}/pyproject.toml +1 -1
  11. kryptools-1.1/tests/test_keccak.py +54 -0
  12. kryptools-1.1/tests/test_sha1.py +16 -0
  13. {kryptools-1.0.2 → kryptools-1.1}/LICENSE +0 -0
  14. {kryptools-1.0.2 → kryptools-1.1}/kryptools/GF2.py +0 -0
  15. {kryptools-1.0.2 → kryptools-1.1}/kryptools/Zmod.py +0 -0
  16. {kryptools-1.0.2 → kryptools-1.1}/kryptools/aes.py +0 -0
  17. {kryptools-1.0.2 → kryptools-1.1}/kryptools/blockcipher.py +0 -0
  18. {kryptools-1.0.2 → kryptools-1.1}/kryptools/conway_polynomials.py +0 -0
  19. {kryptools-1.0.2 → kryptools-1.1}/kryptools/des.py +0 -0
  20. {kryptools-1.0.2 → kryptools-1.1}/kryptools/dlp.py +0 -0
  21. {kryptools-1.0.2 → kryptools-1.1}/kryptools/dlp_bsgs.py +0 -0
  22. {kryptools-1.0.2 → kryptools-1.1}/kryptools/dlp_ic.py +0 -0
  23. {kryptools-1.0.2 → kryptools-1.1}/kryptools/dlp_qs.py +0 -0
  24. {kryptools-1.0.2 → kryptools-1.1}/kryptools/dlp_rho.py +0 -0
  25. {kryptools-1.0.2 → kryptools-1.1}/kryptools/ec.py +0 -0
  26. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor.py +0 -0
  27. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor_dix.py +0 -0
  28. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor_ecm.py +0 -0
  29. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor_fmt.py +0 -0
  30. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor_pm1.py +0 -0
  31. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor_qs.py +0 -0
  32. {kryptools-1.0.2 → kryptools-1.1}/kryptools/factor_rho.py +0 -0
  33. {kryptools-1.0.2 → kryptools-1.1}/kryptools/intfuncs.py +0 -0
  34. {kryptools-1.0.2 → kryptools-1.1}/kryptools/lat.py +0 -0
  35. {kryptools-1.0.2 → kryptools-1.1}/kryptools/nt.py +0 -0
  36. {kryptools-1.0.2 → kryptools-1.1}/kryptools/primes.py +0 -0
  37. {kryptools-1.0.2 → kryptools-1.1}/kryptools.egg-info/dependency_links.txt +0 -0
  38. {kryptools-1.0.2 → kryptools-1.1}/kryptools.egg-info/top_level.txt +0 -0
  39. {kryptools-1.0.2 → kryptools-1.1}/setup.cfg +0 -0
  40. {kryptools-1.0.2 → kryptools-1.1}/tests/test_GF2.py +0 -0
  41. {kryptools-1.0.2 → kryptools-1.1}/tests/test_Zmod.py +0 -0
  42. {kryptools-1.0.2 → kryptools-1.1}/tests/test_aes.py +0 -0
  43. {kryptools-1.0.2 → kryptools-1.1}/tests/test_des.py +0 -0
  44. {kryptools-1.0.2 → kryptools-1.1}/tests/test_dlog.py +0 -0
  45. {kryptools-1.0.2 → kryptools-1.1}/tests/test_ec.py +0 -0
  46. {kryptools-1.0.2 → kryptools-1.1}/tests/test_factor.py +0 -0
  47. {kryptools-1.0.2 → kryptools-1.1}/tests/test_factor_fmt.py +0 -0
  48. {kryptools-1.0.2 → kryptools-1.1}/tests/test_factor_pm1.py +0 -0
  49. {kryptools-1.0.2 → kryptools-1.1}/tests/test_factor_qs.py +0 -0
  50. {kryptools-1.0.2 → kryptools-1.1}/tests/test_intfuncs.py +0 -0
  51. {kryptools-1.0.2 → kryptools-1.1}/tests/test_la.py +0 -0
  52. {kryptools-1.0.2 → kryptools-1.1}/tests/test_lat.py +0 -0
  53. {kryptools-1.0.2 → kryptools-1.1}/tests/test_nt.py +0 -0
  54. {kryptools-1.0.2 → kryptools-1.1}/tests/test_poly.py +0 -0
  55. {kryptools-1.0.2 → kryptools-1.1}/tests/test_primes.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryptools
3
- Version: 1.0.2
3
+ Version: 1.1
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
@@ -49,5 +49,10 @@ The tools contained are:
49
49
  * AESCipher: individual AES operations
50
50
  * DESCipher: individual DES operations
51
51
 
52
+ * SHA1
53
+ * Keccak individual sponge operations
54
+ * SHA3
55
+ * SHAKE
56
+
52
57
  Documentation can be found in the jupyter notebook
53
58
  (mostly done, but might not contain everything: use the force, read the source).
@@ -31,5 +31,10 @@ The tools contained are:
31
31
  * AESCipher: individual AES operations
32
32
  * DESCipher: individual DES operations
33
33
 
34
+ * SHA1
35
+ * Keccak individual sponge operations
36
+ * SHA3
37
+ * SHAKE
38
+
34
39
  Documentation can be found in the jupyter notebook
35
40
  (mostly done, but might not contain everything: use the force, read the source).
@@ -3,9 +3,9 @@ Implemenation of same basic algorithms used in cryptography.
3
3
  """
4
4
 
5
5
  __author__ = "Gerald Teschl"
6
- __copyright__ = "Copyright 2024, Gerald Teschl"
6
+ __copyright__ = "Copyright 2024-2025, Gerald Teschl"
7
7
  __license__ = "MIT License"
8
- __version__ = "1.0.2"
8
+ __version__ = "1.1"
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
@@ -22,3 +22,5 @@ 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
24
  from .des import list2int, int2list, permute, invert_permutation, rotate_left, SDESKeySchedule, SDESCipher, DESKeySchedule, DESCipher, DESBlockCipher
25
+ from .keccak import Keccak, SHA3, SHAKE
26
+ from .sha1 import SHA1
@@ -0,0 +1,203 @@
1
+ """
2
+ Keccak Sponge, SHA3, SHAKE
3
+ """
4
+
5
+
6
+ class Keccak:
7
+ "Keccak sponge"
8
+ MASK_64 = (1 << 64) - 1
9
+ rounds = 24
10
+
11
+ def __init__(self, rate: int = 1088):
12
+ if rate % 64:
13
+ raise ValueError(f"Rate {rate} must be a multiple of 64.")
14
+ self.pad = [b'\x81', b'\x01', b'\x80']
15
+ self.rate = rate // 8 # in bytes
16
+ self.reset()
17
+
18
+ def reset(self):
19
+ self.state = [0] * 25
20
+ self.lfsr = 1
21
+ self.buffer = b''
22
+ self.rnd_bytes = None
23
+
24
+ def __repr__(self):
25
+ out = ""
26
+ for i in range(5):
27
+ for j in range(5):
28
+ out += "%016x" % self.state[5 * i + j]
29
+ if j < 4:
30
+ out += " "
31
+ if i < 4:
32
+ out += "\n"
33
+ return out
34
+
35
+ def f(self) -> None:
36
+ "Apply f to the state."
37
+ self.lfsr = 1
38
+ for r in range(Keccak.rounds):
39
+ self.theta()
40
+ self.pi()
41
+ self.rho()
42
+ self.chi()
43
+ self.iota()
44
+
45
+ def absorb(self, msg: bytes | str) -> None:
46
+ "Absorbe a message into the state."
47
+ if isinstance(msg, str):
48
+ msg = msg.encode()
49
+ msg = self.buffer + msg
50
+ msg_len = len(msg) - len(msg) % self.rate
51
+ msg, self.buffer = msg[:msg_len], msg[msg_len:]
52
+ for i in range(len(msg)//self.rate):
53
+ self.absorb_block(msg[i*self.rate:(i+1)*self.rate])
54
+
55
+ def absorb_block(self, block: bytes) -> None:
56
+ "Absorbe a block into the state. Pad the block if neccessary."
57
+
58
+ if len(block) > self.rate:
59
+ raise ValueError(f"Block must be at most {self.rate} bytes.")
60
+ padlen = self.rate - len(block)
61
+ if padlen == 1:
62
+ block += self.pad[0]
63
+ else:
64
+ block += self.pad[1] + (b'\x00' * (padlen - 2)) + self.pad[2]
65
+ for i in range(len(block)//8):
66
+ self.state[i] ^= int.from_bytes(block[i*8:(i+1)*8], 'little')
67
+ self.f()
68
+
69
+ def squeeze(self, r: int) -> bytes:
70
+ "Squeesze out 'r' bytes from the state."
71
+ if r <= 0:
72
+ raise ValueError("Number of bytes must be positive.")
73
+ if self.rnd_bytes is None:
74
+ self.absorb_block(self.buffer)
75
+ self.rnd_bytes = self.extract_block()
76
+ while r > len(self.rnd_bytes):
77
+ self.f()
78
+ self.rnd_bytes += self.extract_block()
79
+ out, self.rnd_bytes = self.rnd_bytes[:r], self.rnd_bytes[r:]
80
+ return out
81
+
82
+ def extract_block(self) -> bytes:
83
+ "Extract one block from the state."
84
+ out = b''
85
+ for i in range(self.rate//8):
86
+ out += self.state[i].to_bytes(8, 'little')
87
+ return out
88
+
89
+ def left_rotate(self, w: int, n: int) -> int:
90
+ "Left rotate a 64-bit integer w by n bits."
91
+ return ((w << n) & Keccak.MASK_64) | (w >> (64 - n))
92
+
93
+ def theta(self) -> None:
94
+ "Apply Theta to the state."
95
+ v = [0] * 5
96
+ for j in range(5):
97
+ for i in range(5):
98
+ v[j] ^= self.state[5 * i + j]
99
+
100
+ for j in range(5):
101
+ h = v[(j + 4) % 5] ^ self.left_rotate(v[(j + 1) % 5], 1)
102
+ for i in range(5):
103
+ self.state[5 * i + j] ^= h
104
+
105
+ def pi(self) -> None:
106
+ "Apply Pi to the state."
107
+ i, j = 0, 1
108
+
109
+ for t in range(1, 25):
110
+ idx = 5 * i + j
111
+ w = (t * (t + 1) // 2) % 64
112
+ self.state[idx] = self.left_rotate(self.state[idx], w)
113
+ i, j = (3 * i + 2 * j) % 5, i
114
+
115
+ def rho(self) -> None:
116
+ "Apply Rho to the state."
117
+ i, j = 0, 1
118
+ vv = self.state[1]
119
+
120
+ for _ in range(24):
121
+ i, j = (3 * i + 2 * j) % 5, i
122
+ idx = 5 * i + j
123
+ self.state[idx], vv = vv, self.state[idx]
124
+
125
+ def chi(self) -> None:
126
+ "Apply Chi to the state."
127
+ v = [0] * 5
128
+
129
+ for i in range(0, 25, 5):
130
+ for j in range(5):
131
+ v[j] = self.state[i + j]
132
+ for j in range(5):
133
+ self.state[i + j] ^= (v[(j + 1) % 5] ^
134
+ Keccak.MASK_64) & v[(j + 2) % 5]
135
+
136
+ def iota(self) -> None:
137
+ "Apply Iota to the state."
138
+ for w in [0, 1, 3, 7, 15, 31, 63]:
139
+ self.state[0] ^= ((self.lfsr & 1) << w)
140
+ self.lfsr <<= 1
141
+ self.lfsr &= Keccak.MASK_64
142
+ if (self.lfsr & 0x100):
143
+ self.lfsr ^= 0x171
144
+
145
+
146
+ class SHA3():
147
+ """
148
+ SHA3 secure hash algorithm
149
+
150
+ Example:
151
+
152
+ >>>sha3 = SHA3(256)
153
+ >>>sha3("abc").hex()
154
+ '3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532'
155
+ """
156
+
157
+ def __init__(self, n: int = 256):
158
+ if n not in (224, 256, 384, 512):
159
+ raise ValueError(f"n must be one of: 224, 256, 384, 512")
160
+ self.keccak = Keccak(rate=1600-2*n)
161
+ self.keccak.pad = [b'\x86', b'\x06', b'\x80']
162
+ self.hash_length = n // 8 # in bytes
163
+
164
+ def __call__(self, msg: bytes | str) -> bytes:
165
+ "Compute the hash of the message given or absorbed."
166
+ self.keccak.reset()
167
+ self.keccak.absorb(msg)
168
+ return self.keccak.squeeze(self.hash_length)
169
+
170
+ def update(self, msg: bytes | str) -> None:
171
+ "Absorb the given message into the sponge."
172
+ self.keccak.absorb(msg)
173
+
174
+ def digest(self, msg: bytes | str | None = None) -> bytes:
175
+ "Compute the hash of the message given or absorbed."
176
+ if msg is not None:
177
+ self.keccak.absorb(msg)
178
+ digest = self.keccak.squeeze(self.hash_length)
179
+ self.keccak.reset()
180
+ return digest
181
+
182
+
183
+ class SHAKE():
184
+ """
185
+ SHAKE Extendable output function
186
+
187
+ Example:
188
+
189
+ >>> shake = SHAKE(b'secret', n = 128)
190
+ >>> shake(8)
191
+ b'O:dn&\\xb2i>'
192
+ """
193
+
194
+ def __init__(self, msg: bytes | str, n: int = 128) -> None:
195
+ if n not in (128, 256):
196
+ raise ValueError(f"n must be one of: 128, 256")
197
+ self.keccak = Keccak(rate=1600-2*n)
198
+ self.keccak.pad = [b'\x9f', b'\x1f', b'\x80']
199
+ self.keccak.absorb(msg)
200
+
201
+ def __call__(self, r: int) -> bytes:
202
+ "Extract `r` bytes."
203
+ return self.keccak.squeeze(r)
@@ -50,6 +50,12 @@ class Matrix:
50
50
  out[i] += self.__class__.print_post
51
51
  return '\n'.join(out)
52
52
 
53
+ def _repr_mimebundle_(self, **kwargs):
54
+ return {
55
+ "text/plain": self.__repr__(),
56
+ "text/latex": "$\\displaystyle" + self.latex() + "$"
57
+ }
58
+
53
59
  def latex(self) -> str:
54
60
  "Produce LaTeX code for the matrix."
55
61
  res = "\\begin{pmatrix}\n"
@@ -44,12 +44,14 @@ class Poly:
44
44
  def __len__(self):
45
45
  return len(self.coeff)
46
46
 
47
- def __repr__(self):
47
+ def __repr__(self, latex = False):
48
48
  def prx(i: int) -> str:
49
49
  if i == 0:
50
50
  return ""
51
51
  if i == 1:
52
52
  return self.__class__.print_x
53
+ if latex:
54
+ return self.__class__.print_x + "^{" + str(i) +"}"
53
55
  return self.__class__.print_x + self.__class__.print_pow + str(i)
54
56
 
55
57
  if not self:
@@ -91,6 +93,12 @@ class Poly:
91
93
  plus = " + "
92
94
  return tmp.strip()
93
95
 
96
+ def _repr_mimebundle_(self, **kwargs):
97
+ return {
98
+ "text/plain": self.__repr__(),
99
+ "text/latex": "$" + self.__repr__(latex = True) + "$"
100
+ }
101
+
94
102
  def __eq__(self, other):
95
103
  if not isinstance(other, self.__class__):
96
104
  return False
@@ -0,0 +1,86 @@
1
+ """
2
+ SHA1
3
+ """
4
+
5
+ class SHA1:
6
+ "SHA1 Hash function"
7
+
8
+ h_init = (0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0)
9
+
10
+ def __init__(self):
11
+ pass
12
+
13
+ def __call__(self, message: bytes|str, h_init: list = h_init, length: int = None) -> int:
14
+ return self.hash(message, h_init, length)
15
+
16
+ def left_rotate(self, w: int, n: int) -> int:
17
+ """Left rotate a 32-bit integer w by n bits."""
18
+ return ((w << n) | (w >> (32 - n))) & 0xffffffff
19
+ def pad(self, msg: bytes, length: int = None) -> bytes:
20
+ """Pad a message. Optionally augment the message length."""
21
+ msg=bytearray(msg)
22
+ l=len(msg)
23
+ if length:
24
+ l+=length
25
+ msg+=b'\x80'+b'\x00'*((55 - l) % 64) # append 1 plus zeros such that the length % 64 = 56
26
+ msg += int(l*8).to_bytes(8, byteorder='big') # add the bit length of the message
27
+ return bytes(msg)
28
+
29
+ def compression_function(self, h: list, chunk: bytes) -> list:
30
+ """Process a chunk of data and return the new digest variables."""
31
+ assert len(chunk) == 64, "Chunk must be 64 bytes."
32
+
33
+ w = [0] * 80
34
+
35
+ # Break chunk into sixteen 4-byte big-endian words w[i]
36
+ for i in range(16):
37
+ w[i] = int.from_bytes(chunk[i * 4:(i+1) * 4], byteorder='big')
38
+
39
+ # Message schedule: extend the sixteen 32-bit words into eighty 32-bit words
40
+ for i in range(16, 80):
41
+ # Note: SHA-0 differs by not having this leftrotate
42
+ w[i] = self.left_rotate(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16], 1)
43
+
44
+ # Initialize hash value for this chunk
45
+ a, b, c, d, e = h
46
+
47
+ for i in range(80):
48
+ if 0 <= i <= 19:
49
+ # Use alternative 1 for f from FIPS PB 180-1 to avoid bitwise not
50
+ f = d ^ (b & (c ^ d))
51
+ k = 0x5A827999
52
+ elif 20 <= i <= 39:
53
+ f = b ^ c ^ d
54
+ k = 0x6ED9EBA1
55
+ elif 40 <= i <= 59:
56
+ f = (b & c) | (b & d) | (c & d)
57
+ k = 0x8F1BBCDC
58
+ elif 60 <= i <= 79:
59
+ f = b ^ c ^ d
60
+ k = 0xCA62C1D6
61
+
62
+ a, b, c, d, e = ((self.left_rotate(a, 5) + f + e + k + w[i]) & 0xffffffff,
63
+ a, self.left_rotate(b, 30), c, d)
64
+
65
+ # Add this chunk's hash to result so far
66
+ h0 = (h[0] + a) & 0xffffffff
67
+ h1 = (h[1] + b) & 0xffffffff
68
+ h2 = (h[2] + c) & 0xffffffff
69
+ h3 = (h[3] + d) & 0xffffffff
70
+ h4 = (h[4] + e) & 0xffffffff
71
+
72
+ return [h0, h1, h2, h3, h4]
73
+
74
+ def hash(self, message: bytes|str, h_init: list = h_init, length: int = None) -> int:
75
+ """
76
+ Computes SHA1 of a given message.
77
+ Optinally the initial hash can be given and the length of the message can be augmented.
78
+ """
79
+ if isinstance(message, str):
80
+ message = message.encode()
81
+ message= self.pad(message, length)
82
+ h = h_init # initialize the status
83
+ for i in range(0, len(message), 64):
84
+ h = self.compression_function(h, message[i:i+64])
85
+ #return (h[0] << 128) | (h[1] << 96) | (h[2] << 64) | (h[3] << 32) | h[4]
86
+ return b''.join(map(lambda n: int.to_bytes(n,4), h))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryptools
3
- Version: 1.0.2
3
+ Version: 1.1
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
@@ -49,5 +49,10 @@ The tools contained are:
49
49
  * AESCipher: individual AES operations
50
50
  * DESCipher: individual DES operations
51
51
 
52
+ * SHA1
53
+ * Keccak individual sponge operations
54
+ * SHA3
55
+ * SHAKE
56
+
52
57
  Documentation can be found in the jupyter notebook
53
58
  (mostly done, but might not contain everything: use the force, read the source).
@@ -22,11 +22,13 @@ kryptools/factor_pm1.py
22
22
  kryptools/factor_qs.py
23
23
  kryptools/factor_rho.py
24
24
  kryptools/intfuncs.py
25
+ kryptools/keccak.py
25
26
  kryptools/la.py
26
27
  kryptools/lat.py
27
28
  kryptools/nt.py
28
29
  kryptools/poly.py
29
30
  kryptools/primes.py
31
+ kryptools/sha1.py
30
32
  kryptools.egg-info/PKG-INFO
31
33
  kryptools.egg-info/SOURCES.txt
32
34
  kryptools.egg-info/dependency_links.txt
@@ -42,8 +44,10 @@ tests/test_factor_fmt.py
42
44
  tests/test_factor_pm1.py
43
45
  tests/test_factor_qs.py
44
46
  tests/test_intfuncs.py
47
+ tests/test_keccak.py
45
48
  tests/test_la.py
46
49
  tests/test_lat.py
47
50
  tests/test_nt.py
48
51
  tests/test_poly.py
49
- tests/test_primes.py
52
+ tests/test_primes.py
53
+ tests/test_sha1.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryptools"
3
- version = "1.0.2"
3
+ version = "1.1"
4
4
  authors = [
5
5
  { name="Gerald Teschl", email="gerald.teschl@univie.ac.at" },
6
6
  ]
@@ -0,0 +1,54 @@
1
+ import pytest
2
+
3
+ from kryptools import Keccak, SHA3
4
+
5
+
6
+ def test_KECCAK():
7
+ result = [ 0xf1258f7940e1dde7, 0x84d5ccf933c0478a, 0xd598261ea65aa9ee, 0xbd1547306f80494d, 0x8b284e056253d057,
8
+ 0xff97a42d7f8e6fd4, 0x90fee5a0a44647c4, 0x8c5bda0cd6192e76, 0xad30a6f71b19059c, 0x30935ab7d08ffc64,
9
+ 0xeb5aa93f2317d635, 0xa9a6e6260d712103, 0x81a57c16dbcf555f, 0x43b831cd0347c826, 0x1f22f1a11a5569f,
10
+ 0x5e5635a21d9ae61, 0x64befef28cc970f2, 0x613670957bc46611, 0xb87c5a554fd00ecb, 0x8c3ee88a1ccf32c8,
11
+ 0x940c7922ae3a2614, 0x1841f924a2c509e4, 0x16f53526e70465c2, 0x75f644e97f30a13b, 0xeaf1ff7b5ceca249 ]
12
+ keccak = Keccak()
13
+ keccak.f()
14
+ assert keccak.state == result
15
+
16
+
17
+ # https://www.di-mgt.com.au/sha_testvectors.html
18
+ all_tests = [
19
+ {"message" : { "data" : "abc", "count" : 1},
20
+ "SHA-3-224" : "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf",
21
+ "SHA-3-256" : "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532",
22
+ "SHA-3-384" : "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25",
23
+ "SHA-3-512" : "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"
24
+ },
25
+ {"message" : { "data" : "", "count" : 1},
26
+ "SHA-3-224" : "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7",
27
+ "SHA-3-256" : "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
28
+ "SHA-3-384" : "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004",
29
+ "SHA-3-512" : "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"
30
+ },
31
+ {"message" : { "data" : "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "count" : 1},
32
+ "SHA-3-224" : "8a24108b154ada21c9fd5574494479ba5c7e7ab76ef264ead0fcce33",
33
+ "SHA-3-256" : "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376",
34
+ "SHA-3-384" : "991c665755eb3a4b6bbdfb75c78a492e8c56a22c5c4d7e429bfdbc32b9d4ad5aa04a1f076e62fea19eef51acd0657c22",
35
+ "SHA-3-512" : "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e"
36
+ },
37
+ {"message" : { "data" : "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "count" : 1},
38
+ "SHA-3-224" : "543e6868e1666c1a643630df77367ae5a62a85070a51c14cbf665cbc",
39
+ "SHA-3-256" : "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18",
40
+ "SHA-3-384" : "79407d3b5916b59c3e30b09822974791c313fb9ecc849e406f23592d04f625dc8c709b98b43b3852b337216179aa7fc7",
41
+ "SHA-3-512" : "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"
42
+ }
43
+ ]
44
+
45
+ def test_SHA3():
46
+ for test in all_tests:
47
+ msg = bytes(test["message"]["data"], 'utf-8')
48
+ for key in test:
49
+ if key[:5] != "SHA-3":
50
+ continue
51
+ n = int(key[6:])
52
+ h = int(test[key], 16)
53
+ k = SHA3(n)(msg)
54
+ assert int.from_bytes(k, 'big') == h, f"{n}: {msg}"
@@ -0,0 +1,16 @@
1
+ import pytest
2
+
3
+ from kryptools import SHA1
4
+
5
+
6
+ # tests from https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/examples/sha_all.pdf
7
+
8
+ test_vectors = [
9
+ [b'abc', 0xA9993E364706816ABA3E25717850C26C9CD0D89D ],
10
+ [b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 0x84983E441C3BD26EBAAE4AA1F95129E5E54670F1]
11
+ ]
12
+
13
+ def test_sha1():
14
+ sha1 = SHA1()
15
+ for msg, digest in test_vectors:
16
+ assert int.from_bytes(sha1(msg)) == digest
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