mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #30472 -- Simplified Argon2PasswordHasher with argon2-cffi 19.1+ API.
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							ee49cf4f35
						
					
				
				
					commit
					faad809e09
				
			| @@ -307,14 +307,15 @@ class Argon2PasswordHasher(BasePasswordHasher): | ||||
|  | ||||
|     def encode(self, password, salt): | ||||
|         argon2 = self._load_library() | ||||
|         params = self.params() | ||||
|         data = argon2.low_level.hash_secret( | ||||
|             password.encode(), | ||||
|             salt.encode(), | ||||
|             time_cost=self.time_cost, | ||||
|             memory_cost=self.memory_cost, | ||||
|             parallelism=self.parallelism, | ||||
|             hash_len=argon2.DEFAULT_HASH_LENGTH, | ||||
|             type=argon2.low_level.Type.I, | ||||
|             time_cost=params.time_cost, | ||||
|             memory_cost=params.memory_cost, | ||||
|             parallelism=params.parallelism, | ||||
|             hash_len=params.hash_len, | ||||
|             type=params.type, | ||||
|         ) | ||||
|         return self.algorithm + data.decode('ascii') | ||||
|  | ||||
| @@ -323,11 +324,7 @@ class Argon2PasswordHasher(BasePasswordHasher): | ||||
|         algorithm, rest = encoded.split('$', 1) | ||||
|         assert algorithm == self.algorithm | ||||
|         try: | ||||
|             return argon2.low_level.verify_secret( | ||||
|                 ('$' + rest).encode('ascii'), | ||||
|                 password.encode(), | ||||
|                 type=argon2.low_level.Type.I, | ||||
|             ) | ||||
|             return argon2.PasswordHasher().verify('$' + rest, password) | ||||
|         except argon2.exceptions.VerificationError: | ||||
|             return False | ||||
|  | ||||
| @@ -347,22 +344,34 @@ class Argon2PasswordHasher(BasePasswordHasher): | ||||
|         } | ||||
|  | ||||
|     def must_update(self, encoded): | ||||
|         (algorithm, variety, version, time_cost, memory_cost, parallelism, | ||||
|             salt, data) = self._decode(encoded) | ||||
|         algorithm, rest = encoded.split('$', 1) | ||||
|         assert algorithm == self.algorithm | ||||
|         argon2 = self._load_library() | ||||
|         return ( | ||||
|             argon2.low_level.ARGON2_VERSION != version or | ||||
|             self.time_cost != time_cost or | ||||
|             self.memory_cost != memory_cost or | ||||
|             self.parallelism != parallelism | ||||
|         ) | ||||
|         current_params = argon2.extract_parameters('$' + rest) | ||||
|         new_params = self.params() | ||||
|         # Set salt_len to the salt_len of the current parameters because salt | ||||
|         # is explicitly passed to argon2. | ||||
|         new_params.salt_len = current_params.salt_len | ||||
|         return current_params != new_params | ||||
|  | ||||
|     def harden_runtime(self, password, encoded): | ||||
|         # The runtime for Argon2 is too complicated to implement a sensible | ||||
|         # hardening algorithm. | ||||
|         pass | ||||
|  | ||||
|     def params(self): | ||||
|         argon2 = self._load_library() | ||||
|         # salt_len is a noop, because we provide our own salt. | ||||
|         return argon2.Parameters( | ||||
|             type=argon2.low_level.Type.I, | ||||
|             version=argon2.low_level.ARGON2_VERSION, | ||||
|             salt_len=argon2.DEFAULT_RANDOM_SALT_LENGTH, | ||||
|             hash_len=argon2.DEFAULT_HASH_LENGTH, | ||||
|             time_cost=self.time_cost, | ||||
|             memory_cost=self.memory_cost, | ||||
|             parallelism=self.parallelism, | ||||
|         ) | ||||
|  | ||||
|     def _decode(self, encoded): | ||||
|         """ | ||||
|         Split an encoded hash and return: ( | ||||
| @@ -370,24 +379,13 @@ class Argon2PasswordHasher(BasePasswordHasher): | ||||
|             parallelism, salt, data, | ||||
|         ). | ||||
|         """ | ||||
|         bits = encoded.split('$') | ||||
|         if len(bits) == 5: | ||||
|             # Argon2 < 1.3 | ||||
|             algorithm, variety, raw_params, salt, data = bits | ||||
|             version = 0x10 | ||||
|         else: | ||||
|             assert len(bits) == 6 | ||||
|             algorithm, variety, raw_version, raw_params, salt, data = bits | ||||
|             assert raw_version.startswith('v=') | ||||
|             version = int(raw_version[len('v='):]) | ||||
|         params = dict(bit.split('=', 1) for bit in raw_params.split(',')) | ||||
|         assert len(params) == 3 and all(x in params for x in ('t', 'm', 'p')) | ||||
|         time_cost = int(params['t']) | ||||
|         memory_cost = int(params['m']) | ||||
|         parallelism = int(params['p']) | ||||
|         argon2 = self._load_library() | ||||
|         algorithm, rest = encoded.split('$', 1) | ||||
|         params = argon2.extract_parameters('$' + rest) | ||||
|         variety, *_, salt, data = rest.split('$') | ||||
|         return ( | ||||
|             algorithm, variety, version, time_cost, memory_cost, parallelism, | ||||
|             salt, data, | ||||
|             algorithm, variety, params.version, params.time_cost, | ||||
|             params.memory_cost, params.parallelism, salt, data, | ||||
|         ) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -270,7 +270,7 @@ Running all the tests | ||||
| If you want to run the full suite of tests, you'll need to install a number of | ||||
| dependencies: | ||||
|  | ||||
| *  argon2-cffi_ 16.1.0+ | ||||
| *  argon2-cffi_ 19.1.0+ | ||||
| *  asgiref_ 3.2+ (required) | ||||
| *  bcrypt_ | ||||
| *  docutils_ | ||||
|   | ||||
| @@ -324,6 +324,8 @@ Miscellaneous | ||||
| * The :tfilter:`intcomma` and :tfilter:`intword` template filters no longer | ||||
|   depend on the :setting:`USE_L10N` setting. | ||||
|  | ||||
| * Support for ``argon2-cffi`` < 19.1.0 is removed. | ||||
|  | ||||
| .. _deprecated-features-3.2: | ||||
|  | ||||
| Features deprecated in 3.2 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user