13
13
import itertools
14
14
import os
15
15
import sys
16
+ import sysconfig
16
17
import threading
17
18
import unittest
18
19
import warnings
26
27
c_hashlib = import_fresh_module ('hashlib' , fresh = ['_hashlib' ])
27
28
py_hashlib = import_fresh_module ('hashlib' , blocked = ['_hashlib' ])
28
29
30
+ builtin_hashes = sysconfig .get_config_var ("PY_BUILTIN_HASHLIB_HASHES" )
31
+ if builtin_hashes is None :
32
+ builtin_hashes = {'md5' , 'sha1' , 'sha256' , 'sha512' , 'sha3' , 'blake2' }
33
+ else :
34
+ builtin_hashes = {
35
+ m .strip () for m in builtin_hashes .strip ('"' ).lower ().split ("," )
36
+ }
37
+
29
38
try :
30
- from _hashlib import HASH , HASHXOF
39
+ from _hashlib import HASH , HASHXOF , openssl_md_meth_names
31
40
except ImportError :
32
41
HASH = None
33
42
HASHXOF = None
43
+ openssl_md_meth_names = frozenset ()
34
44
35
45
try :
36
46
import _blake2
@@ -175,10 +185,17 @@ def hash_constructors(self):
175
185
constructors = self .constructors_to_test .values ()
176
186
return itertools .chain .from_iterable (constructors )
177
187
188
+ @property
189
+ def is_fips_mode (self ):
190
+ if hasattr (self ._hashlib , "get_fips_mode" ):
191
+ return self ._hashlib .get_fips_mode ()
192
+ else :
193
+ return None
194
+
178
195
def test_hash_array (self ):
179
196
a = array .array ("b" , range (10 ))
180
197
for cons in self .hash_constructors :
181
- c = cons (a )
198
+ c = cons (a , usedforsecurity = False )
182
199
if c .name in self .shakes :
183
200
c .hexdigest (16 )
184
201
else :
@@ -193,14 +210,26 @@ def test_algorithms_available(self):
193
210
self .assertTrue (set (hashlib .algorithms_guaranteed ).
194
211
issubset (hashlib .algorithms_available ))
195
212
196
- def test_usedforsecurity (self ):
213
+ def test_usedforsecurity_true (self ):
214
+ hashlib .new ("sha256" , usedforsecurity = True )
215
+ if self .is_fips_mode :
216
+ self .skipTest ("skip in FIPS mode" )
197
217
for cons in self .hash_constructors :
198
218
cons (usedforsecurity = True )
199
- cons (usedforsecurity = False )
200
219
cons (b'' , usedforsecurity = True )
201
- cons (b'' , usedforsecurity = False )
202
- hashlib .new ("sha256" , usedforsecurity = True )
220
+ hashlib .new ("md5" , usedforsecurity = True )
221
+ hashlib .md5 (usedforsecurity = True )
222
+ if self ._hashlib is not None :
223
+ self ._hashlib .new ("md5" , usedforsecurity = True )
224
+ self ._hashlib .openssl_md5 (usedforsecurity = True )
225
+
226
+ def test_usedforsecurity_false (self ):
203
227
hashlib .new ("sha256" , usedforsecurity = False )
228
+ for cons in self .hash_constructors :
229
+ cons (usedforsecurity = False )
230
+ cons (b'' , usedforsecurity = False )
231
+ hashlib .new ("md5" , usedforsecurity = False )
232
+ hashlib .md5 (usedforsecurity = False )
204
233
if self ._hashlib is not None :
205
234
self ._hashlib .new ("md5" , usedforsecurity = False )
206
235
self ._hashlib .openssl_md5 (usedforsecurity = False )
@@ -240,7 +269,7 @@ def test_get_builtin_constructor(self):
240
269
241
270
def test_hexdigest (self ):
242
271
for cons in self .hash_constructors :
243
- h = cons ()
272
+ h = cons (usedforsecurity = False )
244
273
if h .name in self .shakes :
245
274
self .assertIsInstance (h .digest (16 ), bytes )
246
275
self .assertEqual (hexstr (h .digest (16 )), h .hexdigest (16 ))
@@ -252,7 +281,7 @@ def test_digest_length_overflow(self):
252
281
# See issue #34922
253
282
large_sizes = (2 ** 29 , 2 ** 32 - 10 , 2 ** 32 + 10 , 2 ** 61 , 2 ** 64 - 10 , 2 ** 64 + 10 )
254
283
for cons in self .hash_constructors :
255
- h = cons ()
284
+ h = cons (usedforsecurity = False )
256
285
if h .name not in self .shakes :
257
286
continue
258
287
if HASH is not None and isinstance (h , HASH ):
@@ -266,13 +295,16 @@ def test_digest_length_overflow(self):
266
295
267
296
def test_name_attribute (self ):
268
297
for cons in self .hash_constructors :
269
- h = cons ()
298
+ h = cons (usedforsecurity = False )
270
299
self .assertIsInstance (h .name , str )
271
300
if h .name in self .supported_hash_names :
272
301
self .assertIn (h .name , self .supported_hash_names )
273
302
else :
274
303
self .assertNotIn (h .name , self .supported_hash_names )
275
- self .assertEqual (h .name , hashlib .new (h .name ).name )
304
+ self .assertEqual (
305
+ h .name ,
306
+ hashlib .new (h .name , usedforsecurity = False ).name
307
+ )
276
308
277
309
def test_large_update (self ):
278
310
aas = b'a' * 128
@@ -281,7 +313,7 @@ def test_large_update(self):
281
313
dees = b'd' * 2048 # HASHLIB_GIL_MINSIZE
282
314
283
315
for cons in self .hash_constructors :
284
- m1 = cons ()
316
+ m1 = cons (usedforsecurity = False )
285
317
m1 .update (aas )
286
318
m1 .update (bees )
287
319
m1 .update (cees )
@@ -291,15 +323,15 @@ def test_large_update(self):
291
323
else :
292
324
args = ()
293
325
294
- m2 = cons ()
326
+ m2 = cons (usedforsecurity = False )
295
327
m2 .update (aas + bees + cees + dees )
296
328
self .assertEqual (m1 .digest (* args ), m2 .digest (* args ))
297
329
298
- m3 = cons (aas + bees + cees + dees )
330
+ m3 = cons (aas + bees + cees + dees , usedforsecurity = False )
299
331
self .assertEqual (m1 .digest (* args ), m3 .digest (* args ))
300
332
301
333
# verify copy() doesn't touch original
302
- m4 = cons (aas + bees + cees )
334
+ m4 = cons (aas + bees + cees , usedforsecurity = False )
303
335
m4_digest = m4 .digest (* args )
304
336
m4_copy = m4 .copy ()
305
337
m4_copy .update (dees )
@@ -359,7 +391,7 @@ def check_blocksize_name(self, name, block_size=0, digest_size=0,
359
391
digest_length = None ):
360
392
constructors = self .constructors_to_test [name ]
361
393
for hash_object_constructor in constructors :
362
- m = hash_object_constructor ()
394
+ m = hash_object_constructor (usedforsecurity = False )
363
395
self .assertEqual (m .block_size , block_size )
364
396
self .assertEqual (m .digest_size , digest_size )
365
397
if digest_length :
@@ -418,15 +450,24 @@ def test_blocksize_name_blake2(self):
418
450
self .check_blocksize_name ('blake2s' , 64 , 32 )
419
451
420
452
def test_case_md5_0 (self ):
421
- self .check ('md5' , b'' , 'd41d8cd98f00b204e9800998ecf8427e' )
453
+ self .check (
454
+ 'md5' , b'' , 'd41d8cd98f00b204e9800998ecf8427e' ,
455
+ usedforsecurity = False
456
+ )
422
457
423
458
def test_case_md5_1 (self ):
424
- self .check ('md5' , b'abc' , '900150983cd24fb0d6963f7d28e17f72' )
459
+ self .check (
460
+ 'md5' , b'abc' , '900150983cd24fb0d6963f7d28e17f72' ,
461
+ usedforsecurity = False
462
+ )
425
463
426
464
def test_case_md5_2 (self ):
427
- self .check ('md5' ,
428
- b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' ,
429
- 'd174ab98d277d9f5a5611c2c9f419d9f' )
465
+ self .check (
466
+ 'md5' ,
467
+ b'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' ,
468
+ 'd174ab98d277d9f5a5611c2c9f419d9f' ,
469
+ usedforsecurity = False
470
+ )
430
471
431
472
@unittest .skipIf (sys .maxsize < _4G + 5 , 'test cannot run on 32-bit systems' )
432
473
@bigmemtest (size = _4G + 5 , memuse = 1 , dry_run = False )
@@ -806,22 +847,28 @@ def test_gil(self):
806
847
gil_minsize = 2048
807
848
808
849
for cons in self .hash_constructors :
809
- m = cons ()
850
+ m = cons (usedforsecurity = False )
810
851
m .update (b'1' )
811
852
m .update (b'#' * gil_minsize )
812
853
m .update (b'1' )
813
854
814
- m = cons (b'x' * gil_minsize )
855
+ m = cons (b'x' * gil_minsize , usedforsecurity = False )
815
856
m .update (b'1' )
816
857
817
- m = hashlib .md5 ()
858
+ m = hashlib .sha256 ()
818
859
m .update (b'1' )
819
860
m .update (b'#' * gil_minsize )
820
861
m .update (b'1' )
821
- self .assertEqual (m .hexdigest (), 'cb1e1a2cbc80be75e19935d621fb9b21' )
862
+ self .assertEqual (
863
+ m .hexdigest (),
864
+ '1cfceca95989f51f658e3f3ffe7f1cd43726c9e088c13ee10b46f57cef135b94'
865
+ )
822
866
823
- m = hashlib .md5 (b'x' * gil_minsize )
824
- self .assertEqual (m .hexdigest (), 'cfb767f225d58469c5de3632a8803958' )
867
+ m = hashlib .sha256 (b'1' + b'#' * gil_minsize + b'1' )
868
+ self .assertEqual (
869
+ m .hexdigest (),
870
+ '1cfceca95989f51f658e3f3ffe7f1cd43726c9e088c13ee10b46f57cef135b94'
871
+ )
825
872
826
873
@support .reap_threads
827
874
def test_threaded_hashing (self ):
@@ -859,10 +906,10 @@ def hash_in_chunks(chunk_size):
859
906
860
907
self .assertEqual (expected_hash , hasher .hexdigest ())
861
908
862
- @unittest .skipUnless (hasattr (c_hashlib , 'get_fips_mode' ),
863
- 'need _hashlib.get_fips_mode' )
864
909
def test_get_fips_mode (self ):
865
- self .assertIsInstance (c_hashlib .get_fips_mode (), int )
910
+ fips_mode = self .is_fips_mode
911
+ if fips_mode is not None :
912
+ self .assertIsInstance (fips_mode , int )
866
913
867
914
@unittest .skipUnless (HASH is not None , 'need _hashlib' )
868
915
def test_internal_types (self ):
@@ -934,8 +981,10 @@ class KDFTests(unittest.TestCase):
934
981
(bytes .fromhex ('9d9e9c4cd21fe4be24d5b8244c759665' ), None ),],
935
982
}
936
983
937
- def _test_pbkdf2_hmac (self , pbkdf2 ):
984
+ def _test_pbkdf2_hmac (self , pbkdf2 , supported ):
938
985
for digest_name , results in self .pbkdf2_results .items ():
986
+ if digest_name not in supported :
987
+ continue
939
988
for i , vector in enumerate (self .pbkdf2_test_vectors ):
940
989
password , salt , rounds , dklen = vector
941
990
expected , overwrite_dklen = results [i ]
@@ -946,6 +995,7 @@ def _test_pbkdf2_hmac(self, pbkdf2):
946
995
(digest_name , password , salt , rounds , dklen ))
947
996
out = pbkdf2 (digest_name , memoryview (password ),
948
997
memoryview (salt ), rounds , dklen )
998
+ self .assertEqual (out , expected )
949
999
out = pbkdf2 (digest_name , bytearray (password ),
950
1000
bytearray (salt ), rounds , dklen )
951
1001
self .assertEqual (out , expected )
@@ -967,12 +1017,12 @@ def _test_pbkdf2_hmac(self, pbkdf2):
967
1017
self .assertEqual (out , self .pbkdf2_results ['sha1' ][0 ][0 ])
968
1018
969
1019
def test_pbkdf2_hmac_py (self ):
970
- self ._test_pbkdf2_hmac (py_hashlib .pbkdf2_hmac )
1020
+ self ._test_pbkdf2_hmac (py_hashlib .pbkdf2_hmac , builtin_hashes )
971
1021
972
1022
@unittest .skipUnless (hasattr (c_hashlib , 'pbkdf2_hmac' ),
973
1023
' test requires OpenSSL > 1.0' )
974
1024
def test_pbkdf2_hmac_c (self ):
975
- self ._test_pbkdf2_hmac (c_hashlib .pbkdf2_hmac )
1025
+ self ._test_pbkdf2_hmac (c_hashlib .pbkdf2_hmac , openssl_md_meth_names )
976
1026
977
1027
978
1028
@unittest .skipUnless (hasattr (c_hashlib , 'scrypt' ),
0 commit comments