12
12
# Author: Joachim Strömbergson
13
13
# Copyright (c) 2013 Secworks Sweden AB
14
14
# 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,
34
34
# 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
39
39
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
40
#
41
41
#=======================================================================
56
56
# ChaCha()
57
57
#-------------------------------------------------------------------
58
58
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
60
65
self .verbose = verbose
61
66
self .H = [0 ] * 8
62
67
self .t1 = 0
@@ -88,12 +93,15 @@ def __init__(self, verbose = 0):
88
93
0x391c0cb3 , 0x4ed8aa4a , 0x5b9cca4f , 0x682e6ff3 ,
89
94
0x748f82ee , 0x78a5636f , 0x84c87814 , 0x8cc70208 ,
90
95
0x90befffa , 0xa4506ceb , 0xbef9a3f7 , 0xc67178f2 ]
91
-
92
-
96
+
97
+
93
98
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 ]
97
105
98
106
def next (self , block ):
99
107
self ._W_schedule (block )
@@ -115,25 +123,25 @@ def get_digest(self):
115
123
116
124
117
125
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 ]
125
133
self .h = self .H [7 ]
126
-
127
-
134
+
135
+
128
136
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
137
145
138
146
139
147
def _print_state (self , round ):
@@ -168,7 +176,7 @@ def _next_w(self, round):
168
176
169
177
else :
170
178
tmp_w = (self ._delta1 (self .W [14 ]) +
171
- self .W [9 ] +
179
+ self .W [9 ] +
172
180
self ._delta0 (self .W [1 ]) +
173
181
self .W [0 ]) & 0xffffffff
174
182
for i in range (15 ):
@@ -203,7 +211,7 @@ def _delta0(self, x):
203
211
204
212
def _delta1 (self , x ):
205
213
return (self ._rotr32 (x , 17 ) ^ self ._rotr32 (x , 19 ) ^ self ._shr32 (x , 10 ))
206
-
214
+
207
215
208
216
def _T1 (self , e , f , g , h , k , w ):
209
217
return (h + self ._sigma1 (e ) + self ._Ch (e , f , g ) + k + w ) & 0xffffffff
@@ -216,7 +224,7 @@ def _T2(self, a, b, c):
216
224
def _rotr32 (self , n , r ):
217
225
return ((n >> r ) | (n << (32 - r ))) & 0xffffffff
218
226
219
-
227
+
220
228
def _shr32 (self , n , r ):
221
229
return (n >> r )
222
230
@@ -248,30 +256,104 @@ def compare_digests(digest, expected):
248
256
print_digest (expected )
249
257
else :
250
258
print ("Test case ok." )
251
-
252
-
259
+
260
+
253
261
#-------------------------------------------------------------------
254
- # main ()
262
+ # sha224_tests ()
255
263
#
256
- # If executed tests the ChaCha class using known test vectors .
264
+ # Tests for the SHA224 mode .
257
265
#-------------------------------------------------------------------
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 ():
262
344
263
345
my_sha256 = SHA256 (verbose = 0 );
264
346
265
347
# TC1: NIST testcase with message "abc"
266
348
print ("TC1: Single block message test specified by NIST." )
267
- TC1_block = [0x61626380 , 0x00000000 , 0x00000000 , 0x00000000 ,
349
+ TC1_block = [0x61626380 , 0x00000000 , 0x00000000 , 0x00000000 ,
268
350
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 ,
269
351
0x00000000 , 0x00000000 , 0x00000000 , 0x00000000 ,
270
352
0x00000000 , 0x00000000 , 0x00000000 , 0x00000018 ]
271
-
353
+
272
354
TC1_expected = [0xBA7816BF , 0x8F01CFEA , 0x414140DE , 0x5DAE2223 ,
273
355
0xB00361A3 , 0x96177A9C , 0xB410FF61 , 0xF20015AD ]
274
-
356
+
275
357
my_sha256 .init ()
276
358
my_sha256 .next (TC1_block )
277
359
my_digest = my_sha256 .get_digest ()
@@ -328,14 +410,28 @@ def main():
328
410
print ("Digest for block %d:" % i )
329
411
print_digest (my_digest )
330
412
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
+
332
428
333
429
#-------------------------------------------------------------------
334
430
# __name__
335
431
# Python thingy which allows the file to be run standalone as
336
432
# well as parsed from within a Python interpreter.
337
433
#-------------------------------------------------------------------
338
- if __name__ == "__main__" :
434
+ if __name__ == "__main__" :
339
435
# Run the main function.
340
436
sys .exit (main ())
341
437
0 commit comments