| 
									
										
										
										
											2020-04-29 09:11:29 +08:00
										 |  |  | import functools | 
					
						
							|  |  |  | import hashlib | 
					
						
							|  |  |  | import unittest | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | try: | 
					
						
							|  |  |  |     import _hashlib | 
					
						
							|  |  |  | except ImportError: | 
					
						
							|  |  |  |     _hashlib = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def requires_hashdigest(digestname, openssl=None, usedforsecurity=True): | 
					
						
							|  |  |  |     """Decorator raising SkipTest if a hashing algorithm is not available
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The hashing algorithm could be missing or blocked by a strict crypto | 
					
						
							|  |  |  |     policy. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If 'openssl' is True, then the decorator checks that OpenSSL provides | 
					
						
							|  |  |  |     the algorithm. Otherwise the check falls back to built-in | 
					
						
							|  |  |  |     implementations. The usedforsecurity flag is passed to the constructor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS | 
					
						
							|  |  |  |     ValueError: unsupported hash type md4 | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2021-09-04 23:42:36 +03:00
										 |  |  |     def decorator(func_or_class): | 
					
						
							|  |  |  |         if isinstance(func_or_class, type): | 
					
						
							|  |  |  |             setUpClass = func_or_class.__dict__.get('setUpClass') | 
					
						
							|  |  |  |             if setUpClass is None: | 
					
						
							|  |  |  |                 def setUpClass(cls): | 
					
						
							|  |  |  |                     super(func_or_class, cls).setUpClass() | 
					
						
							|  |  |  |                 setUpClass.__qualname__ = func_or_class.__qualname__ + '.setUpClass' | 
					
						
							|  |  |  |                 setUpClass.__module__ = func_or_class.__module__ | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 setUpClass = setUpClass.__func__ | 
					
						
							|  |  |  |             setUpClass = classmethod(decorator(setUpClass)) | 
					
						
							|  |  |  |             func_or_class.setUpClass = setUpClass | 
					
						
							|  |  |  |             return func_or_class | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         @functools.wraps(func_or_class) | 
					
						
							| 
									
										
										
										
											2020-04-29 09:11:29 +08:00
										 |  |  |         def wrapper(*args, **kwargs): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 if openssl and _hashlib is not None: | 
					
						
							|  |  |  |                     _hashlib.new(digestname, usedforsecurity=usedforsecurity) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     hashlib.new(digestname, usedforsecurity=usedforsecurity) | 
					
						
							|  |  |  |             except ValueError: | 
					
						
							|  |  |  |                 raise unittest.SkipTest( | 
					
						
							|  |  |  |                     f"hash digest '{digestname}' is not available." | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-09-04 23:42:36 +03:00
										 |  |  |             return func_or_class(*args, **kwargs) | 
					
						
							| 
									
										
										
										
											2020-04-29 09:11:29 +08:00
										 |  |  |         return wrapper | 
					
						
							|  |  |  |     return decorator |