diff --git a/owasp-top10-2021-apps/a3/gossip-world/app/model/password.py b/owasp-top10-2021-apps/a3/gossip-world/app/model/password.py index a28925337..88cba0f1f 100644 --- a/owasp-top10-2021-apps/a3/gossip-world/app/model/password.py +++ b/owasp-top10-2021-apps/a3/gossip-world/app/model/password.py @@ -1,4 +1,5 @@ import hashlib +import os class Password: @@ -10,10 +11,22 @@ def get_hashed_password(self): return self._make_hash(self.password) def validate_password(self, hashed_password): - return self._compare_password(hashed_password, self._make_hash(self.password)) + try: + salt, _ = hashed_password.split('$', 1) + except ValueError: + return False + # Recreate hash with extracted salt and compare full stored string + return hashed_password == self._make_hash(self.password, salt) - def _make_hash(self, string): - return hashlib.sha256(string).hexdigest() + def _make_hash(self, string, salt=None): + # Use PBKDF2-HMAC with a random salt and key stretching + if salt is None: + salt = os.urandom(16) + else: + salt = bytes.fromhex(salt) + dk = hashlib.pbkdf2_hmac('sha256', string.encode('utf-8'), salt, 100000) + # Store salt and derived key in hex separated by $ + return salt.hex() + '$' + dk.hex() def _compare_password(self, password_1, password_2): return password_1 == password_2