Python salt and hash password

This code should hashed the password with salt. The salt and hashed password are stored in the database. The password itself is not.

Given the delicate nature of the operation, I wanted to make sure everything was kosher.

import hashlib import base64 import uuid password = 'test_password' salt = base64.urlsafe_b64encode(uuid.uuid4().bytes) t_sha = hashlib.sha512() t_sha.update(password+salt) hashed_password = base64.urlsafe_b64encode(t_sha.digest()) 
+75
python authentication passwords hash salt
Mar 07 2018-12-12T00: 00Z
source share
8 answers

EDIT: This answer is incorrect. One iteration of SHA512 is fast, which makes it unsuitable for use as a password hash function. Use one of the other answers instead.




It looks good on me. However, I’m sure you don’t really need base64. You can simply do this:

 import hashlib, uuid salt = uuid.uuid4().hex hashed_password = hashlib.sha512(password + salt).hexdigest() 

If this does not create difficulties, you can get a slightly more efficient storage in your database by storing the salt and hashed password in the form of raw bytes rather than hexadecimal strings. To do this, replace hex with bytes and hexdigest with digest .

+39
Mar 07 2018-12-12T00:
source share
— -

Based on other answers to this question, I implemented a new approach using bcrypt.

Why use bcrypt

If I understand correctly, the argument for using bcrypt over SHA512 is that bcrypt designed to work slowly. bcrypt also has the ability to configure how slowly you want the first time you generate a hashed password:

 # The '12' is the number that dictates the 'slowness' bcrypt.hashpw(password, bcrypt.gensalt( 12 )) 

Slowing down is desirable because if an attacker gets into a table containing hashed passwords, it will be much harder to trick them.

Implementation

 def get_hashed_password(plain_text_password): # Hash a password for the first time # (Using bcrypt, the salt is saved into the hash itself) return bcrypt.hashpw(plain_text_password, bcrypt.gensalt()) def check_password(plain_text_password, hashed_password): # Check hashed password. Using bcrypt, the salt is saved into the hash itself return bcrypt.checkpw(plain_text_password, hashed_password) 

Notes

I was able to quite easily install the library on a Linux system using:

 pip install py-bcrypt 

However, I had more problems installing it on my Windows systems. It looks like a patch is needed. See this question: installing py-bcrypt on win 7 64bit Python

+52
May 20 '14 at 19:35
source share

The smart thing is not to write to crypto yourself, but to use something like passlib: https://bitbucket.org/ecollins/passlib/wiki/Home

It's easy to mess up your crypto code in a safe way. The disgusting thing is that with non-crypto code, you often immediately notice this when it has not been working since the moment your program crashed. While with crypto code you often discover only after it is late and your data has been compromised. Therefore, I believe that it is better to use a package written by someone else who knows about the subject and which is based on the protocols tested in battle.

In addition, passlib has several useful functions that simplify its use, and can also be easily updated to a new password hashing protocol if the old protocol is broken.

Also, only one round of sha512 is more vulnerable to dictionary attacks. sha512 is designed to be fast, and it's really bad when you try to store passwords securely. Other people thought long and hard about all these kinds of problems, so it’s better to take advantage of this.

+47
Jun 08 '12 at 12:11
source share

For this, in Python 3, you will need UTF-8 encoding, for example:

 hashed_password = hashlib.sha512(password.encode('utf-8') + salt.encode('utf-8')).hexdigest() 

Otherwise, you will receive:

Traceback (last last call):
File "", line 1, on
hashed_password = hashlib.sha512 (password + salt) .hexdigest ()
TypeError: Unicode objects must be encoded before hashing

+19
Jun 10 2018-12-12T00:
source share

passlib seems useful if you need to use hashes stored on an existing system. If you have control over the format, use a modern hash like bcrypt or scrypt. Currently, bcrypt seems to be a lot easier to use from python.

passlib supports bcrypt and recommends installing py-bcrypt as a backend: http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html

You can also use py-bcrypt if you do not want to install passlib. Readme has some basic usage examples.

see also: How to use scrypt to generate a hash for password and salt in Python

+10
Aug 28 '13 at 13:09 on
source share

I don't want to resurrect the old branch, but ... anyone who wants to use a modern and safe solution uses argon2.

https://pypi.python.org/pypi/argon2_cffi

He won the password hashing contest. ( https://password-hashing.net/ ) It is easier to use than bcrypt, and it is more secure than bcrypt.

+6
Aug 14 '17 at 16:56 on
source share

Starting with Python 3.4, the hashlib module in the standard library contains key retrieval functions that are "designed to securely hash passwords."

So use one of them, for example hashlib.pbkdf2_hmac , with the salt generated using os.urandom :

 from typing import Tuple import os import hashlib import hmac def hash_new_password(password: str) -> Tuple[bytes, bytes]: """ Hash the provided password with a randomly-generated salt and return the salt and hash to store in the database. """ salt = os.urandom(16) pw_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) return salt, pw_hash def is_correct_password(salt: bytes, pw_hash: bytes, password: str) -> bool: """ Given a previously-stored salt and hash, and a password provided by a user trying to log in, check whether the password is correct. """ return hmac.compare_digest( pw_hash, hashlib.pbkdf2_hmac('sha256', password.encode(), salt, 100000) ) # Example usage: salt, pw_hash = hash_new_password('correct horse battery staple') assert is_correct_password(salt, pw_hash, 'correct horse battery staple') assert not is_correct_password(salt, pw_hash, 'Tr0ub4dor&3') assert not is_correct_password(salt, pw_hash, 'rosebud') 

Note that:

  • Using 16-byte salt and 100,000 iterations of PBKDF2 matches the minimum numbers recommended in the Python documentation. A further increase in the number of iterations will slow down the calculation of your hashes and, therefore, will make them more secure.
  • os.urandom always uses a cryptographically secure source of randomness
  • hmac.compare_digest used in is_correct_password is basically just a == operator for strings, but without the possibility of a short circuit, which makes it immune to temporary attacks. This probably doesn’t actually give any additional security value , but it will not hurt either, so I went ahead and used it.

For a theory of what makes a good password hash and a list of other functions suitable for password hashing, see https://security.stackexchange.com/q/211/29805 .

+2
Jul 6 '19 at 15:08
source share

First, import: -

 import hashlib, uuid 

Then change your code to match this in your method:

 uname = request.form["uname"] pwd=request.form["pwd"] salt = hashlib.md5(pwd.encode()) 

Then pass this salt and uname in your sql-query to the database, the name of the table is indicated under the login:

 sql = "insert into login values ('"+uname+"','"+email+"','"+salt.hexdigest()+"')" 
0
Mar 21 '19 at 10:32
source share



All Articles