在python中使用Salt和hash一个密码

时间:2022-10-28 18:24:59

This code is supposed to hash a password with a salt. The salt and hashed password are being saved in the database. The password itself is not.

这段代码应该对密码进行哈希处理。将盐和散列密码保存在数据库中。密码本身不是。

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

考虑到手术的敏感性,我想确保一切都是干净的。

Note: I use the url safe version of b64encode out of habit.

注意:我使用了b64encode的url安全版本。

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())

6 个解决方案

#1


30  

EDIT: This answer is wrong. Don't use a cryptographic hash to store passwords. Use a password hash.

编辑:这个答案是错误的。不要使用密码散列来存储密码。使用一个密码散列。


Looks fine by me. However, I'm pretty sure you don't actually need base64. You could just do this:

看起来对我来说不成问题。然而,我很确定你实际上不需要base64。你可以这样做:

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

If it doesn't create difficulties, you can get slightly more efficient storage in your database by storing the salt and hashed password as raw bytes rather than hex strings. To do so, replace hex with bytes and hexdigest with digest.

如果它不产生困难,您可以通过将salt和散列密码存储为原始字节,而不是十六进制字符串,在数据库中获得稍微更有效的存储。为此,用字节替换十六进制,用摘要替换十六进制。

#2


41  

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

聪明的做法不是自己编写密码,而是使用passlib: https://bitbucket.org/ecollins/passlib/wiki/Home

It is easy to mess up writing your crypto code in a secure way. The nasty thing is that with non crypto code you often immediately notice it when it is not working since your program crashes. While with crypto code you often only find out after it is to late and your data has been compromised. Therefor I think it is better to use a package written by someone else who is knowledgable about the subject and which is based on battle tested protocols.

用安全的方式编写密码代码很容易。令人讨厌的是,使用非加密代码时,您常常会在程序崩溃后立即注意到它不工作。使用加密代码时,您通常只会在它过期后才发现,您的数据已经被泄露。因此,我认为最好使用其他人编写的基于战斗测试协议的软件包。

Also passlib has some nice features which make it easy to use and also easy to upgrade to a newer password hashing protocol if an old protocol turns out to be broken.

此外,passlib有一些很好的特性,这些特性使它易于使用,而且如果旧的协议被破坏,也很容易升级到新的密码哈希协议。

Also just a single round of sha512 is more vulnerable to dictionary attacks. sha512 is designed to be fast and this is actually a bad thing when trying to store passwords securely. Other people have thought long and hard about all this sort issues so you better take advantage of this.

此外,只有一圈sha512更容易受到字典攻击。sha512设计得非常快,当试图安全地存储密码时,这实际上是一件坏事。其他人对这类问题思考了很久,所以你最好好好利用它。

#3


40  

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

基于这个问题的其他答案,我使用bcrypt实现了一种新的方法。

Why use bcrypt

If I understand correctly, the argument to use bcrypt over SHA512 is that bcrypt is designed to be slow. bcrypt also has an option to adjust how slow you want it to be when generating the hashed password for the first time:

如果我理解正确的话,使用bcrypt而不是SHA512的理由是bcrypt设计得很慢。bcrypt也有一个选项来调整你第一次生成哈希密码时你想要的速度:

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

Slow is desirable because if a malicious party gets their hands on the table containing hashed passwords, then it is much more difficult to de-encrypt 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 hased password. Useing bcrypt, the salt is saved into the hash itself
    return bcrypt.checkpw(plain_text_password, hashed_password)

Notes

I was able to install the library pretty easily in a linux system using:

我可以很容易地在linux系统中安装这个库,使用:

pip install py-bcrypt

However, I had more trouble installing it on my windows systems. It appears to need a patch. See this * question: py-bcrypt installing on win 7 64bit python

然而,我在windows系统上安装它时遇到了更多的麻烦。它似乎需要一个补丁。请参见这个*问题:在win764bit python上安装py-bcrypt

#4


17  

For this to work in Python 3 you'll need to UTF-8 encode for example:

为了在python3中工作,你需要UTF-8编码,例如:

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

Otherwise you'll get:

否则你会得到:

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

回溯(最近一次调用):File“”,第1行,在hashed_password = hashlib中。sha512(密码+ salt).hexdigest()类型错误:在散列之前,必须对单节点对象进行编码

#5


8  

passlib seems to be useful if you need to use hashes stored by an existing system. If you have control of the format, use a modern hash like bcrypt or scrypt. At this time, bcrypt seems to be much easier to use from python.

如果需要使用现有系统存储的散列,passlib似乎很有用。如果可以控制格式,可以使用bcrypt或scrypt之类的现代散列。此时,从python中使用bcrypt似乎要容易得多。

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

passlib支持bcrypt,并建议安装py-bcrypt作为后端:http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html

You could also use py-bcrypt directly if you don't want to install passlib. The readme has examples of basic use.

如果不想安装passlib,也可以直接使用py-bcrypt。自述有基本用法的例子。

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

参见:如何使用scrypt在Python中为密码和salt生成散列

#6


4  

I don' want to resurrect an old thread, but... anyone who wants to use a modern up to date secure solution, use argon2.

我不想让旧思想复活,但是……任何想要使用最新的安全解决方案的人,请使用argon2。

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

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

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

它赢得了密码哈希竞赛。(https://passwordhash.net/)它比bcrypt更容易使用,而且比bcrypt更安全。

#1


30  

EDIT: This answer is wrong. Don't use a cryptographic hash to store passwords. Use a password hash.

编辑:这个答案是错误的。不要使用密码散列来存储密码。使用一个密码散列。


Looks fine by me. However, I'm pretty sure you don't actually need base64. You could just do this:

看起来对我来说不成问题。然而,我很确定你实际上不需要base64。你可以这样做:

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

If it doesn't create difficulties, you can get slightly more efficient storage in your database by storing the salt and hashed password as raw bytes rather than hex strings. To do so, replace hex with bytes and hexdigest with digest.

如果它不产生困难,您可以通过将salt和散列密码存储为原始字节,而不是十六进制字符串,在数据库中获得稍微更有效的存储。为此,用字节替换十六进制,用摘要替换十六进制。

#2


41  

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

聪明的做法不是自己编写密码,而是使用passlib: https://bitbucket.org/ecollins/passlib/wiki/Home

It is easy to mess up writing your crypto code in a secure way. The nasty thing is that with non crypto code you often immediately notice it when it is not working since your program crashes. While with crypto code you often only find out after it is to late and your data has been compromised. Therefor I think it is better to use a package written by someone else who is knowledgable about the subject and which is based on battle tested protocols.

用安全的方式编写密码代码很容易。令人讨厌的是,使用非加密代码时,您常常会在程序崩溃后立即注意到它不工作。使用加密代码时,您通常只会在它过期后才发现,您的数据已经被泄露。因此,我认为最好使用其他人编写的基于战斗测试协议的软件包。

Also passlib has some nice features which make it easy to use and also easy to upgrade to a newer password hashing protocol if an old protocol turns out to be broken.

此外,passlib有一些很好的特性,这些特性使它易于使用,而且如果旧的协议被破坏,也很容易升级到新的密码哈希协议。

Also just a single round of sha512 is more vulnerable to dictionary attacks. sha512 is designed to be fast and this is actually a bad thing when trying to store passwords securely. Other people have thought long and hard about all this sort issues so you better take advantage of this.

此外,只有一圈sha512更容易受到字典攻击。sha512设计得非常快,当试图安全地存储密码时,这实际上是一件坏事。其他人对这类问题思考了很久,所以你最好好好利用它。

#3


40  

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

基于这个问题的其他答案,我使用bcrypt实现了一种新的方法。

Why use bcrypt

If I understand correctly, the argument to use bcrypt over SHA512 is that bcrypt is designed to be slow. bcrypt also has an option to adjust how slow you want it to be when generating the hashed password for the first time:

如果我理解正确的话,使用bcrypt而不是SHA512的理由是bcrypt设计得很慢。bcrypt也有一个选项来调整你第一次生成哈希密码时你想要的速度:

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

Slow is desirable because if a malicious party gets their hands on the table containing hashed passwords, then it is much more difficult to de-encrypt 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 hased password. Useing bcrypt, the salt is saved into the hash itself
    return bcrypt.checkpw(plain_text_password, hashed_password)

Notes

I was able to install the library pretty easily in a linux system using:

我可以很容易地在linux系统中安装这个库,使用:

pip install py-bcrypt

However, I had more trouble installing it on my windows systems. It appears to need a patch. See this * question: py-bcrypt installing on win 7 64bit python

然而,我在windows系统上安装它时遇到了更多的麻烦。它似乎需要一个补丁。请参见这个*问题:在win764bit python上安装py-bcrypt

#4


17  

For this to work in Python 3 you'll need to UTF-8 encode for example:

为了在python3中工作,你需要UTF-8编码,例如:

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

Otherwise you'll get:

否则你会得到:

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

回溯(最近一次调用):File“”,第1行,在hashed_password = hashlib中。sha512(密码+ salt).hexdigest()类型错误:在散列之前,必须对单节点对象进行编码

#5


8  

passlib seems to be useful if you need to use hashes stored by an existing system. If you have control of the format, use a modern hash like bcrypt or scrypt. At this time, bcrypt seems to be much easier to use from python.

如果需要使用现有系统存储的散列,passlib似乎很有用。如果可以控制格式,可以使用bcrypt或scrypt之类的现代散列。此时,从python中使用bcrypt似乎要容易得多。

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

passlib支持bcrypt,并建议安装py-bcrypt作为后端:http://pythonhosted.org/passlib/lib/passlib.hash.bcrypt.html

You could also use py-bcrypt directly if you don't want to install passlib. The readme has examples of basic use.

如果不想安装passlib,也可以直接使用py-bcrypt。自述有基本用法的例子。

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

参见:如何使用scrypt在Python中为密码和salt生成散列

#6


4  

I don' want to resurrect an old thread, but... anyone who wants to use a modern up to date secure solution, use argon2.

我不想让旧思想复活,但是……任何想要使用最新的安全解决方案的人,请使用argon2。

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

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

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

它赢得了密码哈希竞赛。(https://passwordhash.net/)它比bcrypt更容易使用,而且比bcrypt更安全。