mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #23919 -- Removed obsolete compare_digest() and pbkdf2() implementations.
This commit is contained in:
		| @@ -1,11 +1,9 @@ | ||||
| """ | ||||
| Django's standard crypto functions and utilities. | ||||
| """ | ||||
| import binascii | ||||
| import hashlib | ||||
| import hmac | ||||
| import random | ||||
| import struct | ||||
| import time | ||||
|  | ||||
| from django.conf import settings | ||||
| @@ -73,115 +71,17 @@ def get_random_string(length=12, | ||||
|     return ''.join(random.choice(allowed_chars) for i in range(length)) | ||||
|  | ||||
|  | ||||
| if hasattr(hmac, "compare_digest"): | ||||
|     # Prefer the stdlib implementation, when available. | ||||
|     def constant_time_compare(val1, val2): | ||||
|         return hmac.compare_digest(force_bytes(val1), force_bytes(val2)) | ||||
| else: | ||||
|     def constant_time_compare(val1, val2): | ||||
|         """ | ||||
|         Returns True if the two strings are equal, False otherwise. | ||||
|  | ||||
|         The time taken is independent of the number of characters that match. | ||||
|  | ||||
|         For the sake of simplicity, this function executes in constant time only | ||||
|         when the two strings have the same length. It short-circuits when they | ||||
|         have different lengths. Since Django only uses it to compare hashes of | ||||
|         known expected length, this is acceptable. | ||||
|         """ | ||||
|         if len(val1) != len(val2): | ||||
|             return False | ||||
|         result = 0 | ||||
|         if isinstance(val1, bytes) and isinstance(val2, bytes): | ||||
|             for x, y in zip(val1, val2): | ||||
|                 result |= x ^ y | ||||
|         else: | ||||
|             for x, y in zip(val1, val2): | ||||
|                 result |= ord(x) ^ ord(y) | ||||
|         return result == 0 | ||||
| def constant_time_compare(val1, val2): | ||||
|     """Return True if the two strings are equal, False otherwise.""" | ||||
|     return hmac.compare_digest(force_bytes(val1), force_bytes(val2)) | ||||
|  | ||||
|  | ||||
| def _bin_to_long(x): | ||||
|     """ | ||||
|     Convert a binary string into a long integer | ||||
|  | ||||
|     This is a clever optimization for fast xor vector math | ||||
|     """ | ||||
|     return int(binascii.hexlify(x), 16) | ||||
|  | ||||
|  | ||||
| def _long_to_bin(x, hex_format_string): | ||||
|     """ | ||||
|     Convert a long integer into a binary string. | ||||
|     hex_format_string is like "%020x" for padding 10 characters. | ||||
|     """ | ||||
|     return binascii.unhexlify((hex_format_string % x).encode('ascii')) | ||||
|  | ||||
|  | ||||
| if hasattr(hashlib, "pbkdf2_hmac"): | ||||
|     def pbkdf2(password, salt, iterations, dklen=0, digest=None): | ||||
|         """ | ||||
|         Implements PBKDF2 with the same API as Django's existing | ||||
|         implementation, using the stdlib. | ||||
|  | ||||
|         This is used in Python 2.7.8+ and 3.4+. | ||||
|         """ | ||||
|         if digest is None: | ||||
|             digest = hashlib.sha256 | ||||
|         if not dklen: | ||||
|             dklen = None | ||||
|         password = force_bytes(password) | ||||
|         salt = force_bytes(salt) | ||||
|         return hashlib.pbkdf2_hmac( | ||||
|             digest().name, password, salt, iterations, dklen) | ||||
| else: | ||||
|     def pbkdf2(password, salt, iterations, dklen=0, digest=None): | ||||
|         """ | ||||
|         Implements PBKDF2 as defined in RFC 2898, section 5.2 | ||||
|  | ||||
|         HMAC+SHA256 is used as the default pseudo random function. | ||||
|  | ||||
|         As of 2014, 100,000 iterations was the recommended default which took | ||||
|         100ms on a 2.7Ghz Intel i7 with an optimized implementation. This is | ||||
|         probably the bare minimum for security given 1000 iterations was | ||||
|         recommended in 2001. This code is very well optimized for CPython and | ||||
|         is about five times slower than OpenSSL's implementation. Look in | ||||
|         django.contrib.auth.hashers for the present default, it is lower than | ||||
|         the recommended 100,000 because of the performance difference between | ||||
|         this and an optimized implementation. | ||||
|         """ | ||||
|         assert iterations > 0 | ||||
|         if not digest: | ||||
|             digest = hashlib.sha256 | ||||
|         password = force_bytes(password) | ||||
|         salt = force_bytes(salt) | ||||
|         hlen = digest().digest_size | ||||
|         if not dklen: | ||||
|             dklen = hlen | ||||
|         if dklen > (2 ** 32 - 1) * hlen: | ||||
|             raise OverflowError('dklen too big') | ||||
|         L = -(-dklen // hlen) | ||||
|         r = dklen - (L - 1) * hlen | ||||
|  | ||||
|         hex_format_string = "%%0%ix" % (hlen * 2) | ||||
|  | ||||
|         inner, outer = digest(), digest() | ||||
|         if len(password) > inner.block_size: | ||||
|             password = digest(password).digest() | ||||
|         password += b'\x00' * (inner.block_size - len(password)) | ||||
|         inner.update(password.translate(hmac.trans_36)) | ||||
|         outer.update(password.translate(hmac.trans_5C)) | ||||
|  | ||||
|         def F(i): | ||||
|             u = salt + struct.pack(b'>I', i) | ||||
|             result = 0 | ||||
|             for j in range(int(iterations)): | ||||
|                 dig1, dig2 = inner.copy(), outer.copy() | ||||
|                 dig1.update(u) | ||||
|                 dig2.update(dig1.digest()) | ||||
|                 u = dig2.digest() | ||||
|                 result ^= _bin_to_long(u) | ||||
|             return _long_to_bin(result, hex_format_string) | ||||
|  | ||||
|         T = [F(x) for x in range(1, L)] | ||||
|         return b''.join(T) + F(L)[:r] | ||||
| def pbkdf2(password, salt, iterations, dklen=0, digest=None): | ||||
|     """Return the hash of password using pbkdf2.""" | ||||
|     if digest is None: | ||||
|         digest = hashlib.sha256 | ||||
|     if not dklen: | ||||
|         dklen = None | ||||
|     password = force_bytes(password) | ||||
|     salt = force_bytes(salt) | ||||
|     return hashlib.pbkdf2_hmac(digest().name, password, salt, iterations, dklen) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user