Python密码哈希法

我们将学习密码散列,以及如何用一个名为bcrypt 的第三方库加密盐和散列密码。我们还看看Python中hashlib 库的不同散列算法。

使用Python中的bcrypt 库对密码进行加盐和哈希处理

散列是将一个字符串变成一个固定长度的看似随机的字符串的过程,这个过程是不可逆的。它是一个单向函数,所以你不能像加密那样将哈希值返回到它的原始字符串,你可以对一个信息进行加密,然后再解密。

散列用于用户管理;例如,如果我们有一些数据库漏洞或丢失数据,或者当我们使用明文密码时有人黑进我们的系统。散列给了我们一些保护层;然而,如果我们适当地维护它,散列的密码不容易被破解。

在本节中,我们将看到如何使用bcrypt 模块来处理散列的密码;让我们继续前进,跳入代码。我们将使用一个名为bcrypt 的第三方库,它是一种散列算法。

bcrypt 是一种可靠的、稳健的、被推荐用于散列密码的算法;它给我们提供了一些不错的、简单易用的功能,让我们快速完成工作。

首先,我们将使用以下命令来安装这个库。

pip install bcrypt

现在我们需要导入bcrypt ,创建一个密码,并将其存储在一个变量中,而且这个密码必须是一个字节字符串。为了哈希这个密码,我们将创建一个名为hashed_pswd 的新变量,并调用bcrypthashpw() 方法。

它需要两个参数;第一个是密码,第二个是叫做gensalt() 的东西,随机生成一个数字或一个盐和哈希密码。

import bcrypt
My_pswd = b"Mypassword111"
hashed_pswd = bcrypt.hashpw(My_pswd, bcrypt.gensalt())
print(hashed_pswd)

输出:

b'$2b$12$KEW01pYNDc3ee9U0wZpmgOBpUvvjkig/qxs593hGh/aZ2AvvGTyWu'

使用hashlib 库哈希一个密码

本节将使用hashlib 库来创建一个盐和散列密码。如果你把安全数据如密码之类的东西从一个地方传到另一个地方,最好能确保有人无法读取这些数据。

当你想隐藏一些东西或让用户无法阅读时,有两种类型的事情可以做。第一种是散列法,第二种是加密法;加密法大多不用于密码。

如果我们想把文件从我们的计算机转移到另一台计算机上,或者发送一个文件,那么我们就使用加密。但是,如果我们想检查密码是否正确,或者在我们的服务器中存储密码,那么大多使用散列。

hashlib 库最好的一点是,我们不需要安装任何东西;它是Python 3或更高版本的。在导入hashlib 之后,我们将创建一个名为MD5_Algo 的对象,并从hashlib 中调用md5()

md5 是一种散列算法, 代表 ,而 是版本。现在我们需要将明文转换为散列的字符串,为此,我们调用 方法,并写入我们要散列的字符串。md message-digest 5 update()

然后在print() 函数里面,我们调用hexdigest() 方法;在将应变转换为实际的md5 ,它转换为十六进制形式。

import hashlib
MD5_Algo=hashlib.md5()
MD5_Algo.update('hello')
print(MD5_Algo.hexdigest())

这段代码会抛出一个错误(Unicode对象必须在散列前进行编码),在上一节中,我们已经讨论过,我们需要将字符串转换成字节。

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~AppDataLocalTemp/ipykernel_4064/2416014515.py in <module>
      2
      3 MD5_Algo=hashlib.md5()
----> 4 MD5_Algo.update('hello')
      5 print(MD5_Algo.hexdigest())
TypeError: Unicode-objects must be encoded before hashing

将字符串转换为字节后,我们看到它给了我们一个md5 加密的散列密码。

import hashlib
MD5_Algo=hashlib.md5()
MD5_Algo.update(b'hello')
print(MD5_Algo.hexdigest())

输出:

5d41402abc4b2a76b9719d911017c592

hashlib.sha512()

还有其他种类的加密散列;让我们看看Python里面到底有什么样的散列东西。我们可以使用algorithms_available 属性打印出可用的算法。

print(hashlib.algorithms_available)

输出:

{'md4', 'md5', 'shake_256', 'shake_128', 'sha512_224', 'md5-sha1', 'sha224', 'sha3_512', 'sha1', 'sha3_384', 'sha512', 'sha3_224', 'sha512_256', 'sha384', 'sha256', 'blake2b', 'sha3_256', 'blake2s', 'ripemd160', 'whirlpool', 'sm3', 'mdc2'}

正如我们所看到的,有很多很酷的算法,显然,所有这些对象都有相同的结构,它们会有相同的函数和变量,但只是算法不同而已。

sha512 是我们将使用的,并传入一个字符串;之后,我们对该字符串使用 ,该字符串将被散列。hexdigest()

import hashlib
MD5_Algo=hashlib.sha512(b'hello')
print(MD5_Algo.hexdigest())

当我们运行这段代码时,我们会得到一长串的字符。

9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043

sha512 是比 更强和更好的一种;这完全取决于你在你的情况下确定的更好或最好的方案。sha1

盐化和哈希

这类旧算法的问题是,它们可以被破解或反向工程,而且它并不那么安全,因为每个人都可以轻易地解密这个加密的哈希值。我们的加密哈希值是hello ;如果我们做一个字典攻击,从sha512 字典中解密呢?

Python密码哈希法

sha512 的缺点是,许多人在 Facebook 或其他应用程序上使用他们的密码;通常,他们使用他们的生日,而这些生日已经在sha512 中被反过来看了,所以这就是为什么这不是一个安全的方式。

最安全的方法之一是加盐;加盐会在你的原始字符串前面添加一些字符。比方说,如果我们在"hello" 前面加上"a" ,我们就在原始字符串前面加上了字符"a" 作为盐。

hashlib.sha512(b'helloa')

现在我们已经用这个额外的盐对这个哈希值进行了加密,这就是为什么黑客和其他试图解密这个哈希值的人将会非常困难,所以这就是盐的作用。

hashlib.pbkdf2_hmac()

在Python中,hashlib 库有一个函数,虽然有点慢,但却是一个相当好的函数,叫做pbkdf2_hmac() 。我们将使用这个函数,第二个库实际上是用于将二进制转换为ASCII字符。

pbkdf2_hmac() 需要几个参数;第一个参数是我们将使用的算法的名称,所以我们在这个例子中使用sha512 。下一个是密码或我们要哈希的文本;在这种情况下,它将是"hello"

下一个被称为盐,盐将被添加到这个密码中,然后它们将使用sha512 进行加密。最后一个是迭代次数;如果我们做这个迭代十万次,那么要找到它来解密就非常困难了。

在最后一行代码中,我们使用binascii 库中的hexlify() 方法将加密后的哈希值转换为ASCII字符。

import hashlib, binascii
Enc_Salt = hashlib.pbkdf2_hmac('sha512',b'hello',b'a',100000)
print(binascii.hexlify(Enc_Salt))

输出:

b'40b5957a2d2f5aebcdd878a04e644215d4f3aba3f11c00a1f24e75f8ea2efa11611b2a923a9050832cb768a3a3ad282011cab524b741d392c664b8efbb5f389f'

现在我们可以看到sha512 字典无法解密。

Python密码哈希法