mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #32275 -- Added scrypt password hasher.
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
		
				
					committed by
					
						 Mariusz Felisiak
						Mariusz Felisiak
					
				
			
			
				
	
			
			
			
						parent
						
							65b880b726
						
					
				
				
					commit
					1783b3cb24
				
			| @@ -520,6 +520,7 @@ PASSWORD_HASHERS = [ | ||||
|     'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher', | ||||
|     'django.contrib.auth.hashers.Argon2PasswordHasher', | ||||
|     'django.contrib.auth.hashers.BCryptSHA256PasswordHasher', | ||||
|     'django.contrib.auth.hashers.ScryptPasswordHasher', | ||||
| ] | ||||
|  | ||||
| AUTH_PASSWORD_VALIDATORS = [] | ||||
|   | ||||
| @@ -517,6 +517,81 @@ class BCryptPasswordHasher(BCryptSHA256PasswordHasher): | ||||
|     digest = None | ||||
|  | ||||
|  | ||||
| class ScryptPasswordHasher(BasePasswordHasher): | ||||
|     """ | ||||
|     Secure password hashing using the Scrypt algorithm. | ||||
|     """ | ||||
|     algorithm = 'scrypt' | ||||
|     block_size = 8 | ||||
|     maxmem = 0 | ||||
|     parallelism = 1 | ||||
|     work_factor = 2 ** 14 | ||||
|  | ||||
|     def encode(self, password, salt, n=None, r=None, p=None): | ||||
|         self._check_encode_args(password, salt) | ||||
|         n = n or self.work_factor | ||||
|         r = r or self.block_size | ||||
|         p = p or self.parallelism | ||||
|         hash_ = hashlib.scrypt( | ||||
|             password.encode(), | ||||
|             salt=salt.encode(), | ||||
|             n=n, | ||||
|             r=r, | ||||
|             p=p, | ||||
|             maxmem=self.maxmem, | ||||
|             dklen=64, | ||||
|         ) | ||||
|         hash_ = base64.b64encode(hash_).decode('ascii').strip() | ||||
|         return '%s$%d$%s$%d$%d$%s' % (self.algorithm, n, salt, r, p, hash_) | ||||
|  | ||||
|     def decode(self, encoded): | ||||
|         algorithm, work_factor, salt, block_size, parallelism, hash_ = encoded.split('$', 6) | ||||
|         assert algorithm == self.algorithm | ||||
|         return { | ||||
|             'algorithm': algorithm, | ||||
|             'work_factor': int(work_factor), | ||||
|             'salt': salt, | ||||
|             'block_size': int(block_size), | ||||
|             'parallelism': int(parallelism), | ||||
|             'hash': hash_, | ||||
|         } | ||||
|  | ||||
|     def verify(self, password, encoded): | ||||
|         decoded = self.decode(encoded) | ||||
|         encoded_2 = self.encode( | ||||
|             password, | ||||
|             decoded['salt'], | ||||
|             decoded['work_factor'], | ||||
|             decoded['block_size'], | ||||
|             decoded['parallelism'], | ||||
|         ) | ||||
|         return constant_time_compare(encoded, encoded_2) | ||||
|  | ||||
|     def safe_summary(self, encoded): | ||||
|         decoded = self.decode(encoded) | ||||
|         return { | ||||
|             _('algorithm'): decoded['algorithm'], | ||||
|             _('work factor'): decoded['work_factor'], | ||||
|             _('block size'): decoded['block_size'], | ||||
|             _('parallelism'): decoded['parallelism'], | ||||
|             _('salt'): mask_hash(decoded['salt']), | ||||
|             _('hash'): mask_hash(decoded['hash']), | ||||
|         } | ||||
|  | ||||
|     def must_update(self, encoded): | ||||
|         decoded = self.decode(encoded) | ||||
|         return ( | ||||
|             decoded['work_factor'] != self.work_factor or | ||||
|             decoded['block_size'] != self.block_size or | ||||
|             decoded['parallelism'] != self.parallelism | ||||
|         ) | ||||
|  | ||||
|     def harden_runtime(self, password, encoded): | ||||
|         # The runtime for Scrypt is too complicated to implement a sensible | ||||
|         # hardening algorithm. | ||||
|         pass | ||||
|  | ||||
|  | ||||
| class SHA1PasswordHasher(BasePasswordHasher): | ||||
|     """ | ||||
|     The SHA1 password hashing algorithm (not recommended) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user