Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
import hashlib
import random
import string
def hash_password(password, salt=None, iterations=100000):
"""
Hash a string using SHA3-512
input:
String: password
String: salt (use if you are comparing existing hash)
If empty, it generates new salt
Optional Input:
Int: iterations
How many times the hash hashes itself
should be consistent across your application
Return:
Tuple with the password hash and salt used
Example: (pass_hash, salt)
"""
# Do type checking
if not type(password) == type("String"):
raise TypeError("Password should be a string")
# if no salt is given
# generate 16 alphanumeric long salt using system random
if not salt:
salt = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(16))
# encode to make it compatible with hashlib algorithm
encoded_password = bytes(password, encoding='utf-8')
encoded_salt = bytes(salt, encoding='utf-8')
pass_hash = hashlib.sha3_512(encoded_password+encoded_salt).hexdigest()
# use iterative hashing
for _ in range(iterations):
pass_hash = hashlib.sha3_512(bytes(pass_hash, encoding="utf-8")+encoded_password).hexdigest()
return (pass_hash, salt)
def validate_password(password, pw_hash_tuple):
"""
Check if entered password matches a stored password hash
Input:
String: password
Tuple: pw_hash_tuple
of the scheme: (password_hash, salt)
Output:
Boolean: if they are identical.
"""
# Do input validation
if not len(pw_hash_tuple) == 2:
raise ValueError("pw_hash_tuple should have length 2")
if not type(password) == type('string'):
raise TypeError("password should be a string")
for item in pw_hash_tuple:
if not type(item) == type("string"):
raise TypeError("items in pw_hash_tuple should be strings")
stored_pw_hash = pw_hash_tuple[0]
stored_pw_salt = pw_hash_tuple[1]
# compute the hash of guesspassword using the same salt
user_pw_hash_tuple = hash_password(password, salt=stored_pw_salt)
# compare the two hashes
if user_pw_hash_tuple[0] == stored_pw_hash:
return True
else:
return False
pw_hash_tuple = hash_password("123456")
guess_password = "123456"
print (validate_password(guess_password, pw_hash_tuple)) # True
@camielverdult

This comment has been minimized.

Copy link

camielverdult commented Dec 10, 2019

Wow! This looks great! But I have a question, why are you not using Crypto.Random.get_random_bytes for a random salt? That would make more sense for me security-wise.

Edit: Why are you saving the salt per hash? That would be pretty weak

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.