88
99from test .support import hashlib_helper
1010
11+ try :
12+ from _hashlib import HMAC as C_HMAC
13+ from _hashlib import hmac_new as c_hmac_new
14+ except ImportError :
15+ C_HMAC = None
16+ c_hmac_new = None
17+
1118
1219def ignore_warning (func ):
1320 @functools .wraps (func )
@@ -21,34 +28,91 @@ def wrapper(*args, **kwargs):
2128
2229class TestVectorsTestCase (unittest .TestCase ):
2330
24- @hashlib_helper .requires_hashdigest ('md5' , openssl = True )
25- def test_md5_vectors (self ):
26- # Test the HMAC module against test vectors from the RFC.
31+ def asssert_hmac (
32+ self , key , data , digest , hashfunc , hashname , digest_size , block_size
33+ ):
34+ h = hmac .HMAC (key , data , digestmod = hashfunc )
35+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
36+ self .assertEqual (h .digest (), binascii .unhexlify (digest ))
37+ self .assertEqual (h .name , f"hmac-{ hashname } " )
38+ self .assertEqual (h .digest_size , digest_size )
39+ self .assertEqual (h .block_size , block_size )
40+
41+ h = hmac .HMAC (key , data , digestmod = hashname )
42+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
43+ self .assertEqual (h .digest (), binascii .unhexlify (digest ))
44+ self .assertEqual (h .name , f"hmac-{ hashname } " )
45+ self .assertEqual (h .digest_size , digest_size )
46+ self .assertEqual (h .block_size , block_size )
47+
48+ h = hmac .HMAC (key , digestmod = hashname )
49+ h2 = h .copy ()
50+ h2 .update (b"test update" )
51+ h .update (data )
52+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
53+
54+ h = hmac .new (key , data , digestmod = hashname )
55+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
56+ self .assertEqual (h .digest (), binascii .unhexlify (digest ))
57+ self .assertEqual (h .name , f"hmac-{ hashname } " )
58+ self .assertEqual (h .digest_size , digest_size )
59+ self .assertEqual (h .block_size , block_size )
60+
61+ h = hmac .new (key , None , digestmod = hashname )
62+ h .update (data )
63+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
64+
65+ h = hmac .new (key , digestmod = hashname )
66+ h .update (data )
67+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
68+
69+ h = hmac .new (key , data , digestmod = hashfunc )
70+ self .assertEqual (h .hexdigest ().upper (), digest .upper ())
71+
72+ self .assertEqual (
73+ hmac .digest (key , data , digest = hashname ),
74+ binascii .unhexlify (digest )
75+ )
76+ self .assertEqual (
77+ hmac .digest (key , data , digest = hashfunc ),
78+ binascii .unhexlify (digest )
79+ )
80+ with unittest .mock .patch ('hmac._openssl_md_meths' , {}):
81+ self .assertEqual (
82+ hmac .digest (key , data , digest = hashname ),
83+ binascii .unhexlify (digest )
84+ )
85+ self .assertEqual (
86+ hmac .digest (key , data , digest = hashfunc ),
87+ binascii .unhexlify (digest )
88+ )
2789
28- def md5test ( key , data , digest ) :
29- h = hmac . HMAC (key , data , digestmod = hashlib . md5 )
90+ if c_hmac_new is not None :
91+ h = c_hmac_new (key , data , digestmod = hashname )
3092 self .assertEqual (h .hexdigest ().upper (), digest .upper ())
3193 self .assertEqual (h .digest (), binascii .unhexlify (digest ))
32- self .assertEqual (h .name , "hmac-md5 " )
33- self .assertEqual (h .digest_size , 16 )
34- self .assertEqual (h .block_size , 64 )
94+ self .assertEqual (h .name , f "hmac-{ hashname } " )
95+ self .assertEqual (h .digest_size , digest_size )
96+ self .assertEqual (h .block_size , block_size )
3597
36- h = hmac .HMAC (key , data , digestmod = 'md5' )
98+ h = c_hmac_new (key , digestmod = hashname )
99+ h2 = h .copy ()
100+ h2 .update (b"test update" )
101+ h .update (data )
37102 self .assertEqual (h .hexdigest ().upper (), digest .upper ())
38- self .assertEqual (h .digest (), binascii .unhexlify (digest ))
39- self .assertEqual (h .name , "hmac-md5" )
40- self .assertEqual (h .digest_size , 16 )
41- self .assertEqual (h .block_size , 64 )
42103
43- self .assertEqual (
44- hmac .digest (key , data , digest = 'md5' ),
45- binascii .unhexlify (digest )
104+ @hashlib_helper .requires_hashdigest ('md5' , openssl = True )
105+ def test_md5_vectors (self ):
106+ # Test the HMAC module against test vectors from the RFC.
107+
108+ def md5test (key , data , digest ):
109+ self .asssert_hmac (
110+ key , data , digest ,
111+ hashfunc = hashlib .md5 ,
112+ hashname = "md5" ,
113+ digest_size = 16 ,
114+ block_size = 64
46115 )
47- with unittest .mock .patch ('hmac._openssl_md_meths' , {}):
48- self .assertEqual (
49- hmac .digest (key , data , digest = 'md5' ),
50- binascii .unhexlify (digest )
51- )
52116
53117 md5test (b"\x0b " * 16 ,
54118 b"Hi There" ,
@@ -82,26 +146,14 @@ def md5test(key, data, digest):
82146 @hashlib_helper .requires_hashdigest ('sha1' , openssl = True )
83147 def test_sha_vectors (self ):
84148 def shatest (key , data , digest ):
85- h = hmac .HMAC (key , data , digestmod = hashlib .sha1 )
86- self .assertEqual (h .hexdigest ().upper (), digest .upper ())
87- self .assertEqual (h .digest (), binascii .unhexlify (digest ))
88- self .assertEqual (h .name , "hmac-sha1" )
89- self .assertEqual (h .digest_size , 20 )
90- self .assertEqual (h .block_size , 64 )
91-
92- h = hmac .HMAC (key , data , digestmod = 'sha1' )
93- self .assertEqual (h .hexdigest ().upper (), digest .upper ())
94- self .assertEqual (h .digest (), binascii .unhexlify (digest ))
95- self .assertEqual (h .name , "hmac-sha1" )
96- self .assertEqual (h .digest_size , 20 )
97- self .assertEqual (h .block_size , 64 )
98-
99- self .assertEqual (
100- hmac .digest (key , data , digest = 'sha1' ),
101- binascii .unhexlify (digest )
149+ self .asssert_hmac (
150+ key , data , digest ,
151+ hashfunc = hashlib .sha1 ,
152+ hashname = "sha1" ,
153+ digest_size = 20 ,
154+ block_size = 64
102155 )
103156
104-
105157 shatest (b"\x0b " * 20 ,
106158 b"Hi There" ,
107159 "b617318655057264e28bc0b6fb378c8ef146be00" )
@@ -133,37 +185,15 @@ def shatest(key, data, digest):
133185
134186 def _rfc4231_test_cases (self , hashfunc , hash_name , digest_size , block_size ):
135187 def hmactest (key , data , hexdigests ):
136- hmac_name = "hmac-" + hash_name
137- h = hmac .HMAC (key , data , digestmod = hashfunc )
138- self .assertEqual (h .hexdigest ().lower (), hexdigests [hashfunc ])
139- self .assertEqual (h .name , hmac_name )
140- self .assertEqual (h .digest_size , digest_size )
141- self .assertEqual (h .block_size , block_size )
142-
143- h = hmac .HMAC (key , data , digestmod = hash_name )
144- self .assertEqual (h .hexdigest ().lower (), hexdigests [hashfunc ])
145- self .assertEqual (h .name , hmac_name )
146- self .assertEqual (h .digest_size , digest_size )
147- self .assertEqual (h .block_size , block_size )
148-
149- self .assertEqual (
150- hmac .digest (key , data , digest = hashfunc ),
151- binascii .unhexlify (hexdigests [hashfunc ])
188+ digest = hexdigests [hashfunc ]
189+
190+ self .asssert_hmac (
191+ key , data , digest ,
192+ hashfunc = hashfunc ,
193+ hashname = hash_name ,
194+ digest_size = digest_size ,
195+ block_size = block_size
152196 )
153- self .assertEqual (
154- hmac .digest (key , data , digest = hash_name ),
155- binascii .unhexlify (hexdigests [hashfunc ])
156- )
157-
158- with unittest .mock .patch ('hmac._openssl_md_meths' , {}):
159- self .assertEqual (
160- hmac .digest (key , data , digest = hashfunc ),
161- binascii .unhexlify (hexdigests [hashfunc ])
162- )
163- self .assertEqual (
164- hmac .digest (key , data , digest = hash_name ),
165- binascii .unhexlify (hexdigests [hashfunc ])
166- )
167197
168198 # 4.2. Test Case 1
169199 hmactest (key = b'\x0b ' * 20 ,
@@ -385,6 +415,14 @@ def test_withmodule(self):
385415 except Exception :
386416 self .fail ("Constructor call with hashlib.sha256 raised exception." )
387417
418+ @unittest .skipUnless (C_HMAC is not None , 'need _hashlib' )
419+ def test_internal_types (self ):
420+ # internal types like _hashlib.C_HMAC are not constructable
421+ with self .assertRaisesRegex (
422+ TypeError , "cannot create 'HMAC' instance"
423+ ):
424+ C_HMAC ()
425+
388426
389427class SanityTestCase (unittest .TestCase ):
390428
@@ -395,9 +433,9 @@ def test_exercise_all_methods(self):
395433 try :
396434 h = hmac .HMAC (b"my secret key" , digestmod = "sha256" )
397435 h .update (b"compute the hash of this text!" )
398- dig = h .digest ()
399- dig = h .hexdigest ()
400- h2 = h .copy ()
436+ h .digest ()
437+ h .hexdigest ()
438+ h .copy ()
401439 except Exception :
402440 self .fail ("Exception raised during normal usage of HMAC class." )
403441
@@ -450,6 +488,21 @@ def test_equality(self):
450488 self .assertEqual (h1 .hexdigest (), h2 .hexdigest (),
451489 "Hexdigest of copy doesn't match original hexdigest." )
452490
491+ @hashlib_helper .requires_hashdigest ('sha256' )
492+ def test_equality_new (self ):
493+ # Testing if the copy has the same digests with hmac.new().
494+ h1 = hmac .new (b"key" , digestmod = "sha256" )
495+ h1 .update (b"some random text" )
496+ h2 = h1 .copy ()
497+ self .assertTrue (
498+ id (h1 ) != id (h2 ), "No real copy of the HMAC instance."
499+ )
500+ self .assertEqual (h1 .digest (), h2 .digest (),
501+ "Digest of copy doesn't match original digest." )
502+ self .assertEqual (h1 .hexdigest (), h2 .hexdigest (),
503+ "Hexdigest of copy doesn't match original hexdigest." )
504+
505+
453506class CompareDigestTestCase (unittest .TestCase ):
454507
455508 def test_compare_digest (self ):
0 commit comments