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