Created
June 10, 2012 03:50
-
-
Save gnrfan/2903769 to your computer and use it in GitHub Desktop.
Proper password hashing for web apps in Python
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| Proper password hashing for storing in a web app. | |
| You will need the "simple-pbkdf2" package from PyPi with either | |
| "pip install simple-pbkdf2" or "easy_install simple-pbkdf2" | |
| (c) 2012 - Antonio Ognio <antonio@ognio.com> | |
| """ | |
| from os import urandom | |
| from base64 import b64encode | |
| from hashlib import sha256 | |
| from pbkdf2 import pbkdf2_hex | |
| DEFAULT_SALT_LENGTH = 12 | |
| def generate_salt(length=DEFAULT_SALT_LENGTH): | |
| salt = b64encode(urandom(length)) | |
| return salt | |
| def hash_password(secret, salt): | |
| return pbkdf2_hex( | |
| data=secret, | |
| salt=salt, | |
| hashfunc=sha256 | |
| ) | |
| def check_password(secret, salt, hashed_value): | |
| return hash_password(secret, salt) == hashed_value | |
| def create_password_record(secret): | |
| salt = generate_salt() | |
| return '%s$%s$%s' % ( | |
| 'sha256', | |
| salt, | |
| hash_password(secret, salt) | |
| ) | |
| def check_password_record(secret, record): | |
| try: | |
| funcname, salt, hashed_value = record.split('$') | |
| return check_password(secret, salt, hashed_value) | |
| except ValueError: | |
| return None | |
| def test(): | |
| password = 's3cr3t' | |
| record = create_password_record(password) | |
| failed = check_password_record(password, record) != True | |
| print "Salt of length %d: %s" % ( | |
| DEFAULT_SALT_LENGTH, | |
| generate_salt(DEFAULT_SALT_LENGTH) | |
| ) | |
| print "Testing with password: %s" % password | |
| print "Record: %s" % record | |
| print "Record length: %d" % len(record) | |
| print "Result: %s" % ('Passed.' if not failed else 'Failed.') | |
| raise SystemExit(bool(failed)) | |
| if __name__ == '__main__': | |
| test() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment