@@ -65,44 +65,89 @@ class Implementation(enum.StrEnum):
6565 hashlib = enum .auto ()
6666
6767
68- class HashId (enum .StrEnum ):
69- """Enumeration containing the canonical digest names.
70-
71- Those names should only be used by hashlib.new() or hmac.new().
72- Their support by _hashlib.new() is not necessarily guaranteed.
73- """
68+ class HashFamily (enum .StrEnum ):
69+ """Enumerationg containing the algorithmic families known hashes."""
7470
7571 md5 = enum .auto ()
7672 sha1 = enum .auto ()
73+ sha2 = enum .auto ()
74+ sha3 = enum .auto ()
75+ shake = enum .auto ()
76+ blake2 = enum .auto ()
7777
78- sha224 = enum .auto ()
79- sha256 = enum .auto ()
80- sha384 = enum .auto ()
81- sha512 = enum .auto ()
8278
83- sha3_224 = enum .auto ()
84- sha3_256 = enum .auto ()
85- sha3_384 = enum .auto ()
86- sha3_512 = enum .auto ()
79+ class HashId (enum .StrEnum ):
80+ """Enumeration containing the canonical digest names.
8781
88- shake_128 = enum .auto ()
89- shake_256 = enum .auto ()
82+ Those names should only be used by hashlib.new() or hmac.new().
83+ Their support by _hashlib.new() is not necessarily guaranteed.
84+ """
9085
91- blake2s = enum .auto ()
92- blake2b = enum .auto ()
86+ # MD5 family
87+ md5 = (enum .auto (), HashFamily .md5 )
88+
89+ # SHA-1 family
90+ sha1 = (enum .auto (), HashFamily .sha1 )
91+
92+ # SHA-2 family
93+ sha224 = (enum .auto (), HashFamily .sha2 )
94+ sha256 = (enum .auto (), HashFamily .sha2 )
95+ sha384 = (enum .auto (), HashFamily .sha2 )
96+ sha512 = (enum .auto (), HashFamily .sha2 )
97+
98+ # SHA-3 family
99+ sha3_224 = (enum .auto (), HashFamily .sha3 )
100+ sha3_256 = (enum .auto (), HashFamily .sha3 )
101+ sha3_384 = (enum .auto (), HashFamily .sha3 )
102+ sha3_512 = (enum .auto (), HashFamily .sha3 )
103+
104+ # SHA-3-XOF family
105+ shake_128 = (enum .auto (), HashFamily .shake )
106+ shake_256 = (enum .auto (), HashFamily .shake )
107+
108+ # BLAKE-2 family
109+ blake2s = (enum .auto (), HashFamily .blake2 )
110+ blake2b = (enum .auto (), HashFamily .blake2 )
111+
112+ def __new__ (cls , * args ):
113+ if len (args ) == 1 :
114+ try :
115+ return getattr (cls , args [0 ])
116+ except AttributeError as exc :
117+ raise ValueError (f"unknown hash algorithm: { args [0 ]} " ) from exc
118+ elif len (args ) != 2 :
119+ raise TypeError (f"HashId expects 1 to 2 arguments,"
120+ f" got { len (args )} " )
121+ value , family = args
122+ assert isinstance (family , HashFamily ), family
123+ self = str .__new__ (cls , value )
124+ self ._value_ = value
125+ self ._family = family
126+ return self
93127
94128 def __repr__ (self ):
95129 return str (self )
96130
131+ @classmethod
132+ def from_name (cls , canonical_name ):
133+ if isinstance (canonical_name , cls ):
134+ return canonical_name
135+ return getattr (cls , canonical_name )
136+
137+ @property
138+ def family (self ):
139+ """Get the hash function family."""
140+ return self ._family
141+
97142 @property
98143 def is_xof (self ):
99144 """Indicate whether the hash is an extendable-output hash function."""
100- return self .startswith ( "shake_" )
145+ return self .family is HashFamily . shake
101146
102147 @property
103148 def is_keyed (self ):
104149 """Indicate whether the hash is a keyed hash function."""
105- return self .startswith ( " blake2" )
150+ return self .family is HashFamily . blake2
106151
107152
108153CANONICAL_DIGEST_NAMES = frozenset (map (str , HashId .__members__ ))
0 commit comments