| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -80,6 +80,11 @@ | |||
| 80 | 80 | } | |
| 81 | 81 | ||
| 82 | 82 | def __get_builtin_constructor(name): | |
| 83 | + if not isinstance(name, str): | ||
| 84 | + # Since this function is only used by new(), we use the same | ||
| 85 | + # exception as _hashlib.new() when 'name' is of incorrect type. | ||
| 86 | + err = f"new() argument 'name' must be str, not {type(name).__name__}" | ||
| 87 | + raise TypeError(err) | ||
| 83 | 88 | cache = __builtin_constructor_cache | |
| 84 | 89 | constructor = cache.get(name) | |
| 85 | 90 | if constructor is not None: | |
@@ -120,10 +125,13 @@ def __get_builtin_constructor(name): | |||
| 120 | 125 | if constructor is not None: | |
| 121 | 126 | return constructor | |
| 122 | 127 | ||
| 123 | - raise ValueError('unsupported hash type ' + name) | ||
| 128 | + # Keep the message in sync with hashlib.h::HASHLIB_UNSUPPORTED_ALGORITHM. | ||
| 129 | + raise ValueError(f'unsupported hash algorithm {name}') | ||
| 124 | 130 | ||
| 125 | 131 | ||
| 126 | 132 | def __get_openssl_constructor(name): | |
| 133 | + # This function is only used until the module has been initialized. | ||
| 134 | + assert isinstance(name, str), "invalid call to __get_openssl_constructor()" | ||
| 127 | 135 | if name in __block_openssl_constructor: | |
| 128 | 136 | # Prefer our builtin blake2 implementation. | |
| 129 | 137 | return __get_builtin_constructor(name) | |
@@ -154,6 +162,8 @@ def __hash_new(name, *args, **kwargs): | |||
| 154 | 162 | optionally initialized with data (which must be a bytes-like object). | |
| 155 | 163 | """ | |
| 156 | 164 | if name in __block_openssl_constructor: | |
| 165 | + # __block_openssl_constructor is expected to contain strings only | ||
| 166 | + assert isinstance(name, str), f"unexpected name: {name}" | ||
| 157 | 167 | # Prefer our builtin blake2 implementation. | |
| 158 | 168 | return __get_builtin_constructor(name)(*args, **kwargs) | |
| 159 | 169 | try: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,6 +26,16 @@ | |||
| 26 | 26 | digest_size = None | |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | + def _is_shake_constructor(digest_like): | ||
| 30 | + if isinstance(digest_like, str): | ||
| 31 | + name = digest_like | ||
| 32 | + else: | ||
| 33 | + h = digest_like() if callable(digest_like) else digest_like.new() | ||
| 34 | + if not isinstance(name := getattr(h, "name", None), str): | ||
| 35 | + return False | ||
| 36 | + return name.startswith(("shake", "SHAKE")) | ||
| 37 | + | ||
| 38 | + | ||
| 29 | 39 | def _get_digest_constructor(digest_like): | |
| 30 | 40 | if callable(digest_like): | |
| 31 | 41 | return digest_like | |
@@ -109,6 +119,8 @@ def _init_old(self, key, msg, digestmod): | |||
| 109 | 119 | import warnings | |
| 110 | 120 | ||
| 111 | 121 | digest_cons = _get_digest_constructor(digestmod) | |
| 122 | + if _is_shake_constructor(digest_cons): | ||
| 123 | + raise ValueError(f"unsupported hash algorithm {digestmod}") | ||
| 112 | 124 | ||
| 113 | 125 | self._hmac = None | |
| 114 | 126 | self._outer = digest_cons() | |
@@ -243,6 +255,8 @@ def digest(key, msg, digest): | |||
| 243 | 255 | ||
| 244 | 256 | def _compute_digest_fallback(key, msg, digest): | |
| 245 | 257 | digest_cons = _get_digest_constructor(digest) | |
| 258 | + if _is_shake_constructor(digest_cons): | ||
| 259 | + raise ValueError(f"unsupported hash algorithm {digest}") | ||
| 246 | 260 | inner = digest_cons() | |
| 247 | 261 | outer = digest_cons() | |
| 248 | 262 | blocksize = getattr(inner, 'block_size', 64) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -343,7 +343,9 @@ def test_clinic_signature_errors(self): | |||
| 343 | 343 | ||
| 344 | 344 | def test_unknown_hash(self): | |
| 345 | 345 | self.assertRaises(ValueError, hashlib.new, 'spam spam spam spam spam') | |
| 346 | - self.assertRaises(TypeError, hashlib.new, 1) | ||
| 346 | + # ensure that the exception message remains consistent | ||
| 347 | + err = re.escape("new() argument 'name' must be str, not int") | ||
| 348 | + self.assertRaisesRegex(TypeError, err, hashlib.new, 1) | ||
| 347 | 349 | ||
| 348 | 350 | def test_new_upper_to_lower(self): | |
| 349 | 351 | self.assertEqual(hashlib.new("SHA256").name, "sha256") | |
@@ -370,7 +372,9 @@ def test_get_builtin_constructor(self): | |||
| 370 | 372 | sys.modules['_md5'] = _md5 | |
| 371 | 373 | else: | |
| 372 | 374 | del sys.modules['_md5'] | |
| 373 | - self.assertRaises(TypeError, get_builtin_constructor, 3) | ||
| 375 | + # ensure that the exception message remains consistent | ||
| 376 | + err = re.escape("new() argument 'name' must be str, not int") | ||
| 377 | + self.assertRaises(TypeError, err, get_builtin_constructor, 3) | ||
| 374 | 378 | constructor = get_builtin_constructor('md5') | |
| 375 | 379 | self.assertIs(constructor, _md5.md5) | |
| 376 | 380 | self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5']) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -960,7 +960,7 @@ def raiser(): | |||
| 960 | 960 | with self.assertRaisesRegex(RuntimeError, "custom exception"): | |
| 961 | 961 | func(b'key', b'msg', raiser) | |
| 962 | 962 | ||
| 963 | - with self.assertRaisesRegex(ValueError, 'hash type'): | ||
| 963 | + with self.assertRaisesRegex(ValueError, 'unsupported hash algorithm'): | ||
| 964 | 964 | func(b'key', b'msg', 'unknown') | |
| 965 | 965 | ||
| 966 | 966 | with self.assertRaisesRegex(AttributeError, 'new'): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,4 @@ | |||
| 1 | + :mod:`hashlib`: improve exception messages when a hash algorithm is not | ||
| 2 | + recognized, blocked by the current security policy or incompatible with | ||
| 3 | + the desired operation (for instance, using HMAC with SHAKE). | ||
| 4 | + Patch by Bénédikt Tran. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments