| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 5c5fc9d commit 71d5299
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -300,23 +300,17 @@ include a `salt <https://en.wikipedia.org/wiki/Salt_%28cryptography%29>`_. | |||
| 300 | 300 | ||
| 301 | 301 | >>> from hashlib import pbkdf2_hmac | |
| 302 | 302 | >>> our_app_iters = 500_000 # Application specific, read above. | |
| 303 | - >>> dk = pbkdf2_hmac('sha256', b'password', b'bad salt'*2, our_app_iters) | ||
| 303 | + >>> dk = pbkdf2_hmac('sha256', b'password', b'bad salt' * 2, our_app_iters) | ||
| 304 | 304 | >>> dk.hex() | |
| 305 | 305 | '15530bba69924174860db778f2c6f8104d3aaf9d26241840c8c4a641c8d000a9' | |
| 306 | 306 | ||
| 307 | - .. versionadded:: 3.4 | ||
| 308 | - | ||
| 309 | - .. note:: | ||
| 307 | + Function only available when Python is compiled with OpenSSL. | ||
| 310 | 308 | ||
| 311 | - A fast implementation of *pbkdf2_hmac* is available with OpenSSL. The | ||
| 312 | - Python implementation uses an inline version of :mod:`hmac`. It is about | ||
| 313 | - three times slower and doesn't release the GIL. | ||
| 314 | - | ||
| 315 | - .. deprecated:: 3.10 | ||
| 309 | + .. versionadded:: 3.4 | ||
| 316 | 310 | ||
| 317 | - Slow Python implementation of *pbkdf2_hmac* is deprecated. In the | ||
| 318 | - future the function will only be available when Python is compiled | ||
| 319 | - with OpenSSL. | ||
| 311 | + .. versionchanged:: 3.12 | ||
| 312 | + Function now only available when Python is built with OpenSSL. The slow | ||
| 313 | + pure Python implementation has been removed. | ||
| 320 | 314 | ||
| 321 | 315 | .. function:: scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64) | |
| 322 | 316 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -273,6 +273,12 @@ Removed | |||
| 273 | 273 | use :func:`locale.format_string` instead. | |
| 274 | 274 | (Contributed by Victor Stinner in :gh:`94226`.) | |
| 275 | 275 | ||
| 276 | + * :mod:`hashlib`: Remove the pure Python implementation of | ||
| 277 | + :func:`hashlib.pbkdf2_hmac()`, deprecated in Python 3.10. Python 3.10 and | ||
| 278 | + newer requires OpenSSL 1.1.1 (:pep:`644`): this OpenSSL version provides | ||
| 279 | + a C implementation of :func:`~hashlib.pbkdf2_hmac()` which is faster. | ||
| 280 | + (Contributed by Victor Stinner in :gh:`94199`.) | ||
| 281 | + | ||
| 276 | 282 | ||
| 277 | 283 | Porting to Python 3.12 | |
| 278 | 284 | ====================== | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -65,7 +65,7 @@ | |||
| 65 | 65 | algorithms_available = set(__always_supported) | |
| 66 | 66 | ||
| 67 | 67 | __all__ = __always_supported + ('new', 'algorithms_guaranteed', | |
| 68 | - 'algorithms_available', 'pbkdf2_hmac', 'file_digest') | ||
| 68 | + 'algorithms_available', 'file_digest') | ||
| 69 | 69 | ||
| 70 | 70 | ||
| 71 | 71 | __builtin_constructor_cache = {} | |
@@ -180,72 +180,10 @@ def __hash_new(name, data=b'', **kwargs): | |||
| 180 | 180 | try: | |
| 181 | 181 | # OpenSSL's PKCS5_PBKDF2_HMAC requires OpenSSL 1.0+ with HMAC and SHA | |
| 182 | 182 | from _hashlib import pbkdf2_hmac | |
| 183 | + __all__ += ('pbkdf2_hmac',) | ||
| 183 | 184 | except ImportError: | |
| 184 | - from warnings import warn as _warn | ||
| 185 | - _trans_5C = bytes((x ^ 0x5C) for x in range(256)) | ||
| 186 | - _trans_36 = bytes((x ^ 0x36) for x in range(256)) | ||
| 187 | - | ||
| 188 | - def pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None): | ||
| 189 | - """Password based key derivation function 2 (PKCS #5 v2.0) | ||
| 190 | - | ||
| 191 | - This Python implementations based on the hmac module about as fast | ||
| 192 | - as OpenSSL's PKCS5_PBKDF2_HMAC for short passwords and much faster | ||
| 193 | - for long passwords. | ||
| 194 | - """ | ||
| 195 | - _warn( | ||
| 196 | - "Python implementation of pbkdf2_hmac() is deprecated.", | ||
| 197 | - category=DeprecationWarning, | ||
| 198 | - stacklevel=2 | ||
| 199 | - ) | ||
| 200 | - if not isinstance(hash_name, str): | ||
| 201 | - raise TypeError(hash_name) | ||
| 202 | - | ||
| 203 | - if not isinstance(password, (bytes, bytearray)): | ||
| 204 | - password = bytes(memoryview(password)) | ||
| 205 | - if not isinstance(salt, (bytes, bytearray)): | ||
| 206 | - salt = bytes(memoryview(salt)) | ||
| 207 | - | ||
| 208 | - # Fast inline HMAC implementation | ||
| 209 | - inner = new(hash_name) | ||
| 210 | - outer = new(hash_name) | ||
| 211 | - blocksize = getattr(inner, 'block_size', 64) | ||
| 212 | - if len(password) > blocksize: | ||
| 213 | - password = new(hash_name, password).digest() | ||
| 214 | - password = password + b'\x00' * (blocksize - len(password)) | ||
| 215 | - inner.update(password.translate(_trans_36)) | ||
| 216 | - outer.update(password.translate(_trans_5C)) | ||
| 217 | - | ||
| 218 | - def prf(msg, inner=inner, outer=outer): | ||
| 219 | - # PBKDF2_HMAC uses the password as key. We can re-use the same | ||
| 220 | - # digest objects and just update copies to skip initialization. | ||
| 221 | - icpy = inner.copy() | ||
| 222 | - ocpy = outer.copy() | ||
| 223 | - icpy.update(msg) | ||
| 224 | - ocpy.update(icpy.digest()) | ||
| 225 | - return ocpy.digest() | ||
| 226 | - | ||
| 227 | - if iterations < 1: | ||
| 228 | - raise ValueError(iterations) | ||
| 229 | - if dklen is None: | ||
| 230 | - dklen = outer.digest_size | ||
| 231 | - if dklen < 1: | ||
| 232 | - raise ValueError(dklen) | ||
| 233 | - | ||
| 234 | - dkey = b'' | ||
| 235 | - loop = 1 | ||
| 236 | - from_bytes = int.from_bytes | ||
| 237 | - while len(dkey) < dklen: | ||
| 238 | - prev = prf(salt + loop.to_bytes(4)) | ||
| 239 | - # endianness doesn't matter here as long to / from use the same | ||
| 240 | - rkey = from_bytes(prev) | ||
| 241 | - for i in range(iterations - 1): | ||
| 242 | - prev = prf(prev) | ||
| 243 | - # rkey = rkey ^ prev | ||
| 244 | - rkey ^= from_bytes(prev) | ||
| 245 | - loop += 1 | ||
| 246 | - dkey += rkey.to_bytes(inner.digest_size) | ||
| 247 | - | ||
| 248 | - return dkey[:dklen] | ||
| 185 | + pass | ||
| 186 | + | ||
| 249 | 187 | ||
| 250 | 188 | try: | |
| 251 | 189 | # OpenSSL's scrypt requires OpenSSL 1.1+ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1096,15 +1096,7 @@ def _test_pbkdf2_hmac(self, pbkdf2, supported): | |||
| 1096 | 1096 | iterations=1, dklen=None) | |
| 1097 | 1097 | self.assertEqual(out, self.pbkdf2_results['sha1'][0][0]) | |
| 1098 | 1098 | ||
| 1099 | - @unittest.skipIf(builtin_hashlib is None, "test requires builtin_hashlib") | ||
| 1100 | - def test_pbkdf2_hmac_py(self): | ||
| 1101 | - with warnings_helper.check_warnings(): | ||
| 1102 | - self._test_pbkdf2_hmac( | ||
| 1103 | - builtin_hashlib.pbkdf2_hmac, builtin_hashes | ||
| 1104 | - ) | ||
| 1105 | - | ||
| 1106 | - @unittest.skipUnless(hasattr(openssl_hashlib, 'pbkdf2_hmac'), | ||
| 1107 | - ' test requires OpenSSL > 1.0') | ||
| 1099 | + @unittest.skipIf(openssl_hashlib is None, "requires OpenSSL bindings") | ||
| 1108 | 1100 | def test_pbkdf2_hmac_c(self): | |
| 1109 | 1101 | self._test_pbkdf2_hmac(openssl_hashlib.pbkdf2_hmac, openssl_md_meth_names) | |
| 1110 | 1102 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + :mod:`hashlib`: Remove the pure Python implementation of | ||
| 2 | + :func:`hashlib.pbkdf2_hmac()`, deprecated in Python 3.10. Python 3.10 and | ||
| 3 | + newer requires OpenSSL 1.1.1 (:pep:`644`): this OpenSSL version provides | ||
| 4 | + a C implementation of :func:`~hashlib.pbkdf2_hmac()` which is faster. Patch | ||
| 5 | + by Victor Stinner. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments