Skip to content

Commit 70c528a

Browse files
committed
Adding functionality for both sha224 and sha256 modes in the SHA256 class.
1 parent 8523233 commit 70c528a

File tree

1 file changed

+158
-62
lines changed

1 file changed

+158
-62
lines changed

src/model/python/sha256.py

Lines changed: 158 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,30 @@
1212
# Author: Joachim Strömbergson
1313
# Copyright (c) 2013 Secworks Sweden AB
1414
# All rights reserved.
15-
#
16-
# Redistribution and use in source and binary forms, with or
17-
# without modification, are permitted provided that the following
18-
# conditions are met:
19-
#
20-
# 1. Redistributions of source code must retain the above copyright
21-
# notice, this list of conditions and the following disclaimer.
22-
#
23-
# 2. Redistributions in binary form must reproduce the above copyright
24-
# notice, this list of conditions and the following disclaimer in
25-
# the documentation and/or other materials provided with the
26-
# distribution.
27-
#
28-
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29-
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30-
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31-
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32-
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33-
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
15+
#
16+
# Redistribution and use in source and binary forms, with or
17+
# without modification, are permitted provided that the following
18+
# conditions are met:
19+
#
20+
# 1. Redistributions of source code must retain the above copyright
21+
# notice, this list of conditions and the following disclaimer.
22+
#
23+
# 2. Redistributions in binary form must reproduce the above copyright
24+
# notice, this list of conditions and the following disclaimer in
25+
# the documentation and/or other materials provided with the
26+
# distribution.
27+
#
28+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30+
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31+
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32+
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33+
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
3434
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35-
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36-
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37-
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38-
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37+
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3939
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4040
#
4141
#=======================================================================
@@ -56,7 +56,12 @@
5656
# ChaCha()
5757
#-------------------------------------------------------------------
5858
class SHA256():
59-
def __init__(self, verbose = 0):
59+
def __init__(self, mode="sha256", verbose = 0):
60+
if mode not in ["sha224", "sha256"]:
61+
print("Given mode %s is not supporte." % mode)
62+
return 0
63+
64+
self.mode = mode
6065
self.verbose = verbose
6166
self.H = [0] * 8
6267
self.t1 = 0
@@ -88,12 +93,15 @@ def __init__(self, verbose = 0):
8893
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
8994
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
9095
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]
91-
92-
96+
97+
9398
def init(self):
94-
self.H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
95-
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
96-
99+
if self.mode == "sha356":
100+
self.H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
101+
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]
102+
else:
103+
self.H = [0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
104+
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4]
97105

98106
def next(self, block):
99107
self._W_schedule(block)
@@ -115,25 +123,25 @@ def get_digest(self):
115123

116124

117125
def _copy_digest(self):
118-
self.a = self.H[0]
119-
self.b = self.H[1]
120-
self.c = self.H[2]
121-
self.d = self.H[3]
122-
self.e = self.H[4]
123-
self.f = self.H[5]
124-
self.g = self.H[6]
126+
self.a = self.H[0]
127+
self.b = self.H[1]
128+
self.c = self.H[2]
129+
self.d = self.H[3]
130+
self.e = self.H[4]
131+
self.f = self.H[5]
132+
self.g = self.H[6]
125133
self.h = self.H[7]
126-
127-
134+
135+
128136
def _update_digest(self):
129-
self.H[0] = (self.H[0] + self.a) & 0xffffffff
130-
self.H[1] = (self.H[1] + self.b) & 0xffffffff
131-
self.H[2] = (self.H[2] + self.c) & 0xffffffff
132-
self.H[3] = (self.H[3] + self.d) & 0xffffffff
133-
self.H[4] = (self.H[4] + self.e) & 0xffffffff
134-
self.H[5] = (self.H[5] + self.f) & 0xffffffff
135-
self.H[6] = (self.H[6] + self.g) & 0xffffffff
136-
self.H[7] = (self.H[7] + self.h) & 0xffffffff
137+
self.H[0] = (self.H[0] + self.a) & 0xffffffff
138+
self.H[1] = (self.H[1] + self.b) & 0xffffffff
139+
self.H[2] = (self.H[2] + self.c) & 0xffffffff
140+
self.H[3] = (self.H[3] + self.d) & 0xffffffff
141+
self.H[4] = (self.H[4] + self.e) & 0xffffffff
142+
self.H[5] = (self.H[5] + self.f) & 0xffffffff
143+
self.H[6] = (self.H[6] + self.g) & 0xffffffff
144+
self.H[7] = (self.H[7] + self.h) & 0xffffffff
137145

138146

139147
def _print_state(self, round):
@@ -168,7 +176,7 @@ def _next_w(self, round):
168176

169177
else:
170178
tmp_w = (self._delta1(self.W[14]) +
171-
self.W[9] +
179+
self.W[9] +
172180
self._delta0(self.W[1]) +
173181
self.W[0]) & 0xffffffff
174182
for i in range(15):
@@ -203,7 +211,7 @@ def _delta0(self, x):
203211

204212
def _delta1(self, x):
205213
return (self._rotr32(x, 17) ^ self._rotr32(x, 19) ^ self._shr32(x, 10))
206-
214+
207215

208216
def _T1(self, e, f, g, h, k, w):
209217
return (h + self._sigma1(e) + self._Ch(e, f, g) + k + w) & 0xffffffff
@@ -216,7 +224,7 @@ def _T2(self, a, b, c):
216224
def _rotr32(self, n, r):
217225
return ((n >> r) | (n << (32 - r))) & 0xffffffff
218226

219-
227+
220228
def _shr32(self, n, r):
221229
return (n >> r)
222230

@@ -248,30 +256,104 @@ def compare_digests(digest, expected):
248256
print_digest(expected)
249257
else:
250258
print("Test case ok.")
251-
252-
259+
260+
253261
#-------------------------------------------------------------------
254-
# main()
262+
# sha224_tests()
255263
#
256-
# If executed tests the ChaCha class using known test vectors.
264+
# Tests for the SHA224 mode.
257265
#-------------------------------------------------------------------
258-
def main():
259-
print("Testing the SHA-256 Python model.")
260-
print("---------------------------------")
261-
print
266+
def sha224_tests():
267+
268+
my_sha224 = SHA256(mode="sha224", verbose=0);
269+
270+
# TC1: NIST testcase with message "abc"
271+
print("TC1: Single block message test specified by NIST.")
272+
TC1_block = [0x61626380, 0x00000000, 0x00000000, 0x00000000,
273+
0x00000000, 0x00000000, 0x00000000, 0x00000000,
274+
0x00000000, 0x00000000, 0x00000000, 0x00000000,
275+
0x00000000, 0x00000000, 0x00000000, 0x00000018]
276+
277+
TC1_expected = [0xBA7816BF, 0x8F01CFEA, 0x414140DE, 0x5DAE2223,
278+
0xB00361A3, 0x96177A9C, 0xB410FF61, 0xF20015AD]
279+
280+
my_sha224.init()
281+
my_sha224.next(TC1_block)
282+
my_digest = my_sha224.get_digest()
283+
compare_digests(my_digest, TC1_expected)
284+
print("")
285+
286+
287+
# TC2: NIST testcase with double block message."
288+
print("TC2: Double block message test specified by NIST.")
289+
TC2_1_block = [0x61626364, 0x62636465, 0x63646566, 0x64656667,
290+
0x65666768, 0x66676869, 0x6768696A, 0x68696A6B,
291+
0x696A6B6C, 0x6A6B6C6D, 0x6B6C6D6E, 0x6C6D6E6F,
292+
0x6D6E6F70, 0x6E6F7071, 0x80000000, 0x00000000]
293+
294+
295+
TC2_2_block = [0x00000000, 0x00000000, 0x00000000, 0x00000000,
296+
0x00000000, 0x00000000, 0x00000000, 0x00000000,
297+
0x00000000, 0x00000000, 0x00000000, 0x00000000,
298+
0x00000000, 0x00000000, 0x00000000, 0x000001C0]
299+
300+
TC2_1_expected = [0x85E655D6, 0x417A1795, 0x3363376A, 0x624CDE5C,
301+
0x76E09589, 0xCAC5F811, 0xCC4B32C1, 0xF20E533A]
302+
303+
TC2_2_expected = [0x248D6A61, 0xD20638B8, 0xE5C02693, 0x0C3E6039,
304+
0xA33CE459, 0x64FF2167, 0xF6ECEDD4, 0x19DB06C1]
305+
306+
my_sha224.init()
307+
my_sha224.next(TC2_1_block)
308+
my_digest = my_sha224.get_digest()
309+
compare_digests(my_digest, TC2_1_expected)
310+
311+
my_sha224.next(TC2_2_block)
312+
my_digest = my_sha224.get_digest()
313+
compare_digests(my_digest, TC2_2_expected)
314+
print("")
315+
316+
317+
# TC3: Huge message with n blocks
318+
n = 1000
319+
print("TC3: Huge message with %d blocks test case." % n)
320+
TC3_block = [0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
321+
0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
322+
0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f,
323+
0xaa55aa55, 0xdeadbeef, 0x55aa55aa, 0xf00ff00f]
324+
325+
TC3_expected = [0x7638f3bc, 0x500dd1a6, 0x586dd4d0, 0x1a1551af,
326+
0xd821d235, 0x2f919e28, 0xd5842fab, 0x03a40f2a]
327+
328+
my_sha224.init()
329+
for i in range(n):
330+
my_sha224.next(TC3_block)
331+
my_digest = my_sha224.get_digest()
332+
if (VERBOSE):
333+
print("Digest for block %d:" % i)
334+
print_digest(my_digest)
335+
compare_digests(my_digest, TC3_expected)
336+
337+
338+
#-------------------------------------------------------------------
339+
# sha256_tests()
340+
#
341+
# Tests for the SHA256 mode.
342+
#-------------------------------------------------------------------
343+
def sha256_tests():
262344

263345
my_sha256 = SHA256(verbose=0);
264346

265347
# TC1: NIST testcase with message "abc"
266348
print("TC1: Single block message test specified by NIST.")
267-
TC1_block = [0x61626380, 0x00000000, 0x00000000, 0x00000000,
349+
TC1_block = [0x61626380, 0x00000000, 0x00000000, 0x00000000,
268350
0x00000000, 0x00000000, 0x00000000, 0x00000000,
269351
0x00000000, 0x00000000, 0x00000000, 0x00000000,
270352
0x00000000, 0x00000000, 0x00000000, 0x00000018]
271-
353+
272354
TC1_expected = [0xBA7816BF, 0x8F01CFEA, 0x414140DE, 0x5DAE2223,
273355
0xB00361A3, 0x96177A9C, 0xB410FF61, 0xF20015AD]
274-
356+
275357
my_sha256.init()
276358
my_sha256.next(TC1_block)
277359
my_digest = my_sha256.get_digest()
@@ -328,14 +410,28 @@ def main():
328410
print("Digest for block %d:" % i)
329411
print_digest(my_digest)
330412
compare_digests(my_digest, TC3_expected)
331-
413+
414+
415+
#-------------------------------------------------------------------
416+
# main()
417+
#
418+
# If executed tests the ChaCha class using known test vectors.
419+
#-------------------------------------------------------------------
420+
def main():
421+
print("Testing the SHA-256 Python model.")
422+
print("---------------------------------")
423+
print
424+
425+
sha224_tests()
426+
sha256_tests()
427+
332428

333429
#-------------------------------------------------------------------
334430
# __name__
335431
# Python thingy which allows the file to be run standalone as
336432
# well as parsed from within a Python interpreter.
337433
#-------------------------------------------------------------------
338-
if __name__=="__main__":
434+
if __name__=="__main__":
339435
# Run the main function.
340436
sys.exit(main())
341437

0 commit comments

Comments
 (0)