bpo-38153: Normalize hashlib algorithm names (GH-16083)

Signed-off-by: Christian Heimes <christian@python.org>
diff --git a/Lib/hashlib.py b/Lib/hashlib.py
index 4e783a8..56873b7 100644
--- a/Lib/hashlib.py
+++ b/Lib/hashlib.py
@@ -70,37 +70,44 @@
 
 __builtin_constructor_cache = {}
 
+__block_openssl_constructor = {
+    'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
+    'shake_128', 'shake_256',
+    'blake2b', 'blake2s',
+}
+
 def __get_builtin_constructor(name):
     cache = __builtin_constructor_cache
     constructor = cache.get(name)
     if constructor is not None:
         return constructor
     try:
-        if name in ('SHA1', 'sha1'):
+        if name in {'SHA1', 'sha1'}:
             import _sha1
             cache['SHA1'] = cache['sha1'] = _sha1.sha1
-        elif name in ('MD5', 'md5'):
+        elif name in {'MD5', 'md5'}:
             import _md5
             cache['MD5'] = cache['md5'] = _md5.md5
-        elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'):
+        elif name in {'SHA256', 'sha256', 'SHA224', 'sha224'}:
             import _sha256
             cache['SHA224'] = cache['sha224'] = _sha256.sha224
             cache['SHA256'] = cache['sha256'] = _sha256.sha256
-        elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'):
+        elif name in {'SHA512', 'sha512', 'SHA384', 'sha384'}:
             import _sha512
             cache['SHA384'] = cache['sha384'] = _sha512.sha384
             cache['SHA512'] = cache['sha512'] = _sha512.sha512
-        elif name in ('blake2b', 'blake2s'):
+        elif name in {'blake2b', 'blake2s'}:
             import _blake2
             cache['blake2b'] = _blake2.blake2b
             cache['blake2s'] = _blake2.blake2s
-        elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
-                      'shake_128', 'shake_256'}:
+        elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512'}:
             import _sha3
             cache['sha3_224'] = _sha3.sha3_224
             cache['sha3_256'] = _sha3.sha3_256
             cache['sha3_384'] = _sha3.sha3_384
             cache['sha3_512'] = _sha3.sha3_512
+        elif name in {'shake_128', 'shake_256'}:
+            import _sha3
             cache['shake_128'] = _sha3.shake_128
             cache['shake_256'] = _sha3.shake_256
     except ImportError:
@@ -114,8 +121,8 @@
 
 
 def __get_openssl_constructor(name):
-    if name in {'blake2b', 'blake2s'}:
-        # Prefer our blake2 implementation.
+    if name in __block_openssl_constructor:
+        # Prefer our blake2 and sha3 implementation.
         return __get_builtin_constructor(name)
     try:
         f = getattr(_hashlib, 'openssl_' + name)
@@ -140,8 +147,8 @@
     """new(name, data=b'') - Return a new hashing object using the named algorithm;
     optionally initialized with data (which must be a bytes-like object).
     """
-    if name in {'blake2b', 'blake2s'}:
-        # Prefer our blake2 implementation.
+    if name in __block_openssl_constructor:
+        # Prefer our blake2 and sha3 implementation
         # OpenSSL 1.1.0 comes with a limited implementation of blake2b/s.
         # It does neither support keyed blake2 nor advanced features like
         # salt, personal, tree hashing or SSE.
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 46088e5..9204b44 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -27,6 +27,11 @@
 py_hashlib = import_fresh_module('hashlib', blocked=['_hashlib'])
 
 try:
+    from _hashlib import HASH
+except ImportError:
+    HASH = None
+
+try:
     import _blake2
 except ImportError:
     _blake2 = None
@@ -386,6 +391,9 @@
         constructors = self.constructors_to_test[name]
         for hash_object_constructor in constructors:
             m = hash_object_constructor()
+            if HASH is not None and isinstance(m, HASH):
+                # _hashopenssl's variant does not have extra SHA3 attributes
+                continue
             self.assertEqual(capacity + rate, 1600)
             self.assertEqual(m._capacity_bits, capacity)
             self.assertEqual(m._rate_bits, rate)
@@ -985,6 +993,10 @@
                 hashlib.scrypt(b'password', salt=b'salt', n=2, r=8, p=1,
                                dklen=dklen)
 
+    def test_normalized_name(self):
+        self.assertNotIn("blake2b512", hashlib.algorithms_available)
+        self.assertNotIn("sha3-512", hashlib.algorithms_available)
+
 
 if __name__ == "__main__":
     unittest.main()