@@ -198,6 +198,61 @@ def invalid_implementation_error(self, implementation):
198198 return AssertionError (msg )
199199
200200
201+ class _HashTypeInfo (_HashInfoBase ):
202+ """Dataclass containing information for hash functions types.
203+
204+ - *builtin* is the fully-qualified name for the builtin HACL* type,
205+ e.g., "_md5.MD5Type".
206+
207+ - *openssl* is the fully-qualified name for the OpenSSL wrapper type,
208+ e.g., "_hashlib.HASH".
209+ """
210+
211+ def __init__ (self , canonical_name , builtin , openssl ):
212+ super ().__init__ (canonical_name )
213+ self .builtin = _HashInfoItem (builtin , strict = True )
214+ self .openssl = _HashInfoItem (openssl , strict = True )
215+
216+ def fullname (self , implementation ):
217+ """Get the fully qualified name of a given implementation.
218+
219+ This returns a string of the form "MODULE_NAME.OBJECT_NAME" or None
220+ if the hash function does not have a corresponding implementation.
221+
222+ *implementation* must be "builtin" or "openssl".
223+ """
224+ return self [implementation ].fullname
225+
226+ def module_name (self , implementation ):
227+ """Get the name of the module containing the hash object type."""
228+ return self [implementation ].module_name
229+
230+ def object_type_name (self , implementation ):
231+ """Get the name of the hash object class name."""
232+ return self [implementation ].member_name
233+
234+ def import_module (self , implementation , * , allow_skip = False ):
235+ """Import the module containing the hash object type.
236+
237+ On error, return None if *allow_skip* is false, or raise SkipNoHash.
238+ """
239+ module = self [implementation ].import_module ()
240+ if allow_skip and module is None :
241+ raise SkipNoHash (self .canonical_name , implementation )
242+ return module
243+
244+ def import_object_type (self , implementation , * , allow_skip = False ):
245+ """Get the runtime hash object type.
246+
247+ On error, return None if *allow_skip* is false, or raise SkipNoHash.
248+ """
249+ member = self [implementation ].import_member ()
250+ if allow_skip and member is None :
251+ raise SkipNoHash (self .name , implementation , interface = "class" )
252+ assert isinstance (member , type | None ), member
253+ return member
254+
255+
201256class _HashFuncInfo (_HashInfoBase ):
202257 """Dataclass containing information for hash functions constructors.
203258
@@ -247,6 +302,12 @@ def method_name(self, implementation):
247302class _HashInfo :
248303 """Dataclass containing information for supported hash functions.
249304
305+ - *builtin_object_type_fullname* is the fully-qualified name
306+ for the builtin HACL* type, e.g., "_md5.MD5Type".
307+
308+ - *openssl_object_type_fullname* is the fully-qualified name
309+ for the OpenSSL wrapper type, i.e. "_hashlib.HASH" or "_hashlib.HASHXOF".
310+
250311 - *builtin_method_fullname* is the fully-qualified name
251312 of the HACL* hash constructor function, e.g., "_md5.md5".
252313
@@ -262,11 +323,19 @@ class _HashInfo:
262323 def __init__ (
263324 self ,
264325 name ,
326+ builtin_object_type_fullname ,
327+ openssl_object_type_fullname ,
265328 builtin_method_fullname ,
266329 openssl_method_fullname = None ,
267330 hashlib_method_fullname = None ,
268331 ):
269332 self .name = name
333+
334+ self .type = _HashTypeInfo (
335+ name ,
336+ builtin_object_type_fullname ,
337+ openssl_object_type_fullname ,
338+ )
270339 self .func = _HashFuncInfo (
271340 name ,
272341 builtin_method_fullname ,
@@ -278,92 +347,126 @@ def __init__(
278347_HASHINFO_DATABASE = MappingProxyType ({
279348 HashId .md5 : _HashInfo (
280349 HashId .md5 ,
350+ "_md5.MD5Type" ,
351+ "_hashlib.HASH" ,
281352 "_md5.md5" ,
282353 "_hashlib.openssl_md5" ,
283354 "hashlib.md5" ,
284355 ),
285356 HashId .sha1 : _HashInfo (
286357 HashId .sha1 ,
358+ "_sha1.SHA1Type" ,
359+ "_hashlib.HASH" ,
287360 "_sha1.sha1" ,
288361 "_hashlib.openssl_sha1" ,
289362 "hashlib.sha1" ,
290363 ),
291364 HashId .sha224 : _HashInfo (
292365 HashId .sha224 ,
366+ "_sha2.SHA224Type" ,
367+ "_hashlib.HASH" ,
293368 "_sha2.sha224" ,
294369 "_hashlib.openssl_sha224" ,
295370 "hashlib.sha224" ,
296371 ),
297372 HashId .sha256 : _HashInfo (
298373 HashId .sha256 ,
374+ "_sha2.SHA256Type" ,
375+ "_hashlib.HASH" ,
299376 "_sha2.sha256" ,
300377 "_hashlib.openssl_sha256" ,
301378 "hashlib.sha256" ,
302379 ),
303380 HashId .sha384 : _HashInfo (
304381 HashId .sha384 ,
382+ "_sha2.SHA384Type" ,
383+ "_hashlib.HASH" ,
305384 "_sha2.sha384" ,
306385 "_hashlib.openssl_sha384" ,
307386 "hashlib.sha384" ,
308387 ),
309388 HashId .sha512 : _HashInfo (
310389 HashId .sha512 ,
390+ "_sha2.SHA512Type" ,
391+ "_hashlib.HASH" ,
311392 "_sha2.sha512" ,
312393 "_hashlib.openssl_sha512" ,
313394 "hashlib.sha512" ,
314395 ),
315396 HashId .sha3_224 : _HashInfo (
316397 HashId .sha3_224 ,
317398 "_sha3.sha3_224" ,
399+ "_hashlib.HASH" ,
400+ "_sha3.sha3_224" ,
318401 "_hashlib.openssl_sha3_224" ,
319402 "hashlib.sha3_224" ,
320403 ),
321404 HashId .sha3_256 : _HashInfo (
322405 HashId .sha3_256 ,
323406 "_sha3.sha3_256" ,
407+ "_hashlib.HASH" ,
408+ "_sha3.sha3_256" ,
324409 "_hashlib.openssl_sha3_256" ,
325410 "hashlib.sha3_256" ,
326411 ),
327412 HashId .sha3_384 : _HashInfo (
328413 HashId .sha3_384 ,
329414 "_sha3.sha3_384" ,
415+ "_hashlib.HASH" ,
416+ "_sha3.sha3_384" ,
330417 "_hashlib.openssl_sha3_384" ,
331418 "hashlib.sha3_384" ,
332419 ),
333420 HashId .sha3_512 : _HashInfo (
334421 HashId .sha3_512 ,
335422 "_sha3.sha3_512" ,
423+ "_hashlib.HASH" ,
424+ "_sha3.sha3_512" ,
336425 "_hashlib.openssl_sha3_512" ,
337426 "hashlib.sha3_512" ,
338427 ),
339428 HashId .shake_128 : _HashInfo (
340429 HashId .shake_128 ,
341430 "_sha3.shake_128" ,
431+ "_hashlib.HASHXOF" ,
432+ "_sha3.shake_128" ,
342433 "_hashlib.openssl_shake_128" ,
343434 "hashlib.shake_128" ,
344435 ),
345436 HashId .shake_256 : _HashInfo (
346437 HashId .shake_256 ,
347438 "_sha3.shake_256" ,
439+ "_hashlib.HASHXOF" ,
440+ "_sha3.shake_256" ,
348441 "_hashlib.openssl_shake_256" ,
349442 "hashlib.shake_256" ,
350443 ),
351444 HashId .blake2s : _HashInfo (
352445 HashId .blake2s ,
353446 "_blake2.blake2s" ,
447+ "_hashlib.HASH" ,
448+ "_blake2.blake2s" ,
354449 None ,
355450 "hashlib.blake2s" ,
356451 ),
357452 HashId .blake2b : _HashInfo (
358453 HashId .blake2b ,
359454 "_blake2.blake2b" ,
455+ "_hashlib.HASH" ,
456+ "_blake2.blake2b" ,
360457 None ,
361458 "hashlib.blake2b" ,
362459 ),
363460})
364461assert _HASHINFO_DATABASE .keys () == CANONICAL_DIGEST_NAMES
365462
366463
464+ def get_hash_type_info (name ):
465+ info = _HASHINFO_DATABASE [name ]
466+ assert isinstance (info , _HashInfo ), info
467+ return info .type
468+
469+
367470def get_hash_func_info (name ):
368471 info = _HASHINFO_DATABASE [name ]
369472 assert isinstance (info , _HashInfo ), info
0 commit comments