Python's safest method to store and retrieve passwords from a database

烈酒焚心 提交于 2019-11-27 17:27:30
rz.

Store the password+salt as a hash and the salt. Take a look at how Django does it: basic docs and source. In the db they store <type of hash>$<salt>$<hash> in a single char field. You can also store the three parts in separate fields.

The function to set the password:

def set_password(self, raw_password):
    import random
    algo = 'sha1'
    salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
    hsh = get_hexdigest(algo, salt, raw_password)
    self.password = '%s$%s$%s' % (algo, salt, hsh)

The get_hexdigest is just a thin wrapper around some hashing algorithms. You can use hashlib for that. Something like hashlib.sha1('%s%s' % (salt, hash)).hexdigest()

And the function to check the password:

def check_password(raw_password, enc_password):
    """
    Returns a boolean of whether the raw_password was correct. Handles
    encryption formats behind the scenes.
    """
    algo, salt, hsh = enc_password.split('$')
    return hsh == get_hexdigest(algo, salt, raw_password)
M.D.

I think it is best to use a package dedicated to hashing passwords for this like passlib: http://packages.python.org/passlib/ for reasons as I explained here: https://stackoverflow.com/a/10948614/893857

Terrel Shumway

I answered this here: https://stackoverflow.com/a/18488878/1661689, and so did @Koffie.

I don't know how to emphasize enough that the accepted answer is NOT secure. It is better than plain text, and better than an unsalted hash, but it is still extremely vulnerable to dictionary and even brute-force attacks. Instead, please use a SLOW KDF like bcrypt (or at least PBKDF2 with 10,000 iterations)

If you have enough control over both endpoints of the application, the absolute best way is using PAK-Z+.

(Edited: the original version recommended SRP but PAK-Z+ has a proof of security.)

llazzaro

Here is a simpler way (taken from effbot), provided passwords with a length greater than 8 will not be a problem*:

import crypt

import random, string

def getsalt(chars = string.letters + string.digits):
    # generate a random 2-character 'salt'
    return random.choice(chars) + random.choice(chars)

for generate the password :

crypt.crypt("password", getsalt())

*: A password with a length greater than 8 is stripped from the right down to 8 chars long

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!