5353
5454"""
5555
56+ # This tuple and __get_builtin_constructor() must be modified if a new
57+ # always available algorithm is added.
58+ __always_supported = ('md5' , 'sha1' , 'sha224' , 'sha256' , 'sha384' , 'sha512' )
59+
60+ __all__ = __always_supported + ('new' ,)
61+
5662
5763def __get_builtin_constructor (name ):
5864 if name in ('SHA1' , 'sha1' ):
@@ -76,7 +82,19 @@ def __get_builtin_constructor(name):
7682 elif bs == '384' :
7783 return _sha512 .sha384
7884
79- raise ValueError ("unsupported hash type" )
85+ raise ValueError ('unsupported hash type %s' % name )
86+
87+
88+ def __get_openssl_constructor (name ):
89+ try :
90+ f = getattr (_hashlib , 'openssl_' + name )
91+ # Allow the C module to raise ValueError. The function will be
92+ # defined but the hash not actually available thanks to OpenSSL.
93+ f ()
94+ # Use the C function directly (very fast)
95+ return f
96+ except (AttributeError , ValueError ):
97+ return __get_builtin_constructor (name )
8098
8199
82100def __py_new (name , data = b'' ):
@@ -102,39 +120,21 @@ def __hash_new(name, data=b''):
102120
103121try :
104122 import _hashlib
105- # use the wrapper of the C implementation
106123 new = __hash_new
107-
108- for opensslFuncName in filter (lambda n : n .startswith ('openssl_' ), dir (_hashlib )):
109- funcName = opensslFuncName [len ('openssl_' ):]
110- try :
111- # try them all, some may not work due to the OpenSSL
112- # version not supporting that algorithm.
113- f = getattr (_hashlib , opensslFuncName )
114- f ()
115- # Use the C function directly (very fast)
116- exec (funcName + ' = f' )
117- except ValueError :
118- try :
119- # Use the builtin implementation directly (fast)
120- exec (funcName + ' = __get_builtin_constructor(funcName)' )
121- except ValueError :
122- # this one has no builtin implementation, don't define it
123- pass
124- # clean up our locals
125- del f
126- del opensslFuncName
127- del funcName
128-
124+ __get_hash = __get_openssl_constructor
129125except ImportError :
130- # We don't have the _hashlib OpenSSL module?
131- # use the built in legacy interfaces via a wrapper function
132126 new = __py_new
127+ __get_hash = __get_builtin_constructor
128+
129+ for __func_name in __always_supported :
130+ # try them all, some may not work due to the OpenSSL
131+ # version not supporting that algorithm.
132+ try :
133+ globals ()[__func_name ] = __get_hash (__func_name )
134+ except ValueError :
135+ import logging
136+ logging .exception ('code for hash %s was not found.' , __func_name )
133137
134- # lookup the C function to use directly for the named constructors
135- md5 = __get_builtin_constructor ('md5' )
136- sha1 = __get_builtin_constructor ('sha1' )
137- sha224 = __get_builtin_constructor ('sha224' )
138- sha256 = __get_builtin_constructor ('sha256' )
139- sha384 = __get_builtin_constructor ('sha384' )
140- sha512 = __get_builtin_constructor ('sha512' )
138+ # Cleanup locals()
139+ del __always_supported , __func_name , __get_hash
140+ del __py_new , __hash_new , __get_openssl_constructor
0 commit comments