11
11
import hashlib
12
12
import importlib
13
13
import itertools
14
+ import json
14
15
import os
15
16
import sys
16
17
import sysconfig
28
29
COMPILED_WITH_PYDEBUG = hasattr (sys , 'gettotalrefcount' )
29
30
30
31
# default builtin hash module
31
- default_builtin_hashes = {'md5' , 'sha1' , 'sha256' , 'sha512' , 'sha3' , 'blake2' }
32
+ default_builtin_hashes = {'md5' , 'sha1' , 'sha256' , 'sha512' , 'sha3' , 'blake2' , 'blake3' }
32
33
# --with-builtin-hashlib-hashes override
33
34
builtin_hashes = sysconfig .get_config_var ("PY_BUILTIN_HASHLIB_HASHES" )
34
35
if builtin_hashes is None :
@@ -64,6 +65,13 @@ def get_fips_mode():
64
65
65
66
requires_blake2 = unittest .skipUnless (_blake2 , 'requires _blake2' )
66
67
68
+ try :
69
+ import _blake3
70
+ except ImportError :
71
+ _blake3 = None
72
+
73
+ requires_blake3 = unittest .skipUnless (_blake3 , 'requires _blake3' )
74
+
67
75
# bpo-46913: Don't test the _sha3 extension on a Python UBSAN build
68
76
SKIP_SHA3 = support .check_sanitizer (ub = True )
69
77
requires_sha3 = unittest .skipUnless (not SKIP_SHA3 , 'requires _sha3' )
@@ -100,7 +108,7 @@ class HashLibTestCase(unittest.TestCase):
100
108
supported_hash_names = ( 'md5' , 'MD5' , 'sha1' , 'SHA1' ,
101
109
'sha224' , 'SHA224' , 'sha256' , 'SHA256' ,
102
110
'sha384' , 'SHA384' , 'sha512' , 'SHA512' ,
103
- 'blake2b' , 'blake2s' ,
111
+ 'blake2b' , 'blake2s' , 'blake3' ,
104
112
'sha3_224' , 'sha3_256' , 'sha3_384' , 'sha3_512' ,
105
113
'shake_128' , 'shake_256' )
106
114
@@ -127,6 +135,10 @@ def __init__(self, *args, **kwargs):
127
135
if _blake2 :
128
136
algorithms .update ({'blake2b' , 'blake2s' })
129
137
138
+ _blake3 = self ._conditional_import_module ('_blake3' )
139
+ if _blake3 :
140
+ algorithms .add ('blake3' )
141
+
130
142
self .constructors_to_test = {}
131
143
for algorithm in algorithms :
132
144
if SKIP_SHA3 and algorithm .startswith ('sha3_' ):
@@ -182,6 +194,8 @@ def add_builtin_constructor(name):
182
194
if _blake2 :
183
195
add_builtin_constructor ('blake2s' )
184
196
add_builtin_constructor ('blake2b' )
197
+ if _blake3 :
198
+ add_builtin_constructor ('blake3' )
185
199
186
200
if not SKIP_SHA3 :
187
201
_sha3 = self ._conditional_import_module ('_sha3' )
@@ -390,6 +404,10 @@ def test_no_unicode_blake2(self):
390
404
self .check_no_unicode ('blake2b' )
391
405
self .check_no_unicode ('blake2s' )
392
406
407
+ @requires_blake3
408
+ def test_no_unicode_blake3 (self ):
409
+ self .check_no_unicode ('blake3' )
410
+
393
411
@requires_sha3
394
412
def test_no_unicode_sha3 (self ):
395
413
self .check_no_unicode ('sha3_224' )
@@ -461,6 +479,10 @@ def test_blocksize_name_blake2(self):
461
479
self .check_blocksize_name ('blake2b' , 128 , 64 )
462
480
self .check_blocksize_name ('blake2s' , 64 , 32 )
463
481
482
+ @requires_blake3
483
+ def test_blocksize_name_blake3 (self ):
484
+ self .check_blocksize_name ('blake3' , 64 , 32 )
485
+
464
486
def test_case_md5_0 (self ):
465
487
self .check (
466
488
'md5' , b'' , 'd41d8cd98f00b204e9800998ecf8427e' ,
@@ -787,6 +809,59 @@ def test_blake2s_vectors(self):
787
809
key = bytes .fromhex (key )
788
810
self .check ('blake2s' , msg , md , key = key )
789
811
812
+ @requires_blake3
813
+ def test_blake3_vectors (self ):
814
+ base_data = b'' .join ([bytes ((i ,)) for i in range (0 , 251 )])
815
+ data = base_data * 408
816
+
817
+ path = os .path .dirname (__file__ ) + "/blake3.test_vectors.json"
818
+ with open (path , "rb" ) as f :
819
+ test_vectors = json .load (f )
820
+
821
+ blake3_key = test_vectors ['key' ].encode ('ascii' )
822
+ blake3_derive_key_context = test_vectors ['context_string' ].encode ('ascii' )
823
+
824
+ def test (case ):
825
+ nonlocal data
826
+ length = case ['input_len' ]
827
+ truncated = data [:length ]
828
+
829
+ styles = ['stock' , 'initialized stock' , 'key' , 'derived_key' ]
830
+ for style in styles :
831
+ update = True
832
+ if style == 'stock' :
833
+ b = hashlib .blake3 ()
834
+ expected = case ['hash' ]
835
+ elif style == 'initialized stock' :
836
+ b = hashlib .blake3 (truncated )
837
+ expected = case ['hash' ]
838
+ update = False
839
+ elif style == 'key' :
840
+ b = hashlib .blake3 (b'' , key = blake3_key )
841
+ expected = case ['keyed_hash' ]
842
+ elif style == 'derived_key' :
843
+ b = hashlib .blake3 (derive_key_context = blake3_derive_key_context )
844
+ expected = case ['derive_key' ]
845
+
846
+ if update :
847
+ b .update (truncated )
848
+
849
+ copy = b .copy ()
850
+
851
+ for hasher in [b , copy ]:
852
+ got = hasher .hexdigest (length = len (expected ) // 2 )
853
+ self .assertEqual (expected , got , f"\n \n didn't get the right long hash!\n { style = } \n { length = } \n \n { expected = } \n \n { got = } \n " )
854
+
855
+ expected = expected [:b .output_length * 2 ]
856
+ got = hasher .hexdigest ()
857
+ self .assertEqual (expected , got , f"\n \n didn't get the right default-length hash!\n { style = } \n { length = } \n \n { expected = } \n \n { got = } \n " )
858
+
859
+ got = hasher .digest ().hex ()
860
+ self .assertEqual (expected , got , f"\n \n didn't get the right default-length digest!\n { style = } \n { length = } \n \n { expected = } \n \n { got = } \n " )
861
+
862
+ for case in test_vectors ['cases' ]:
863
+ test (case )
864
+
790
865
@requires_sha3
791
866
def test_case_sha3_224_0 (self ):
792
867
self .check ('sha3_224' , b"" ,
0 commit comments