- hashlib 模块
- 密码加密
- 密码撞库
- 密码加盐
一,hashlib模块
hashlib模块是用来为字符串进行加密的模块,通过该作用就可以为用户的密码进行加密。
通过模块中的hash算法可以为任意长度的字符串加密成长度相同的一串hash值。该hash算法得到的hash值有一下几个特点:
- 经过同一个hash算法为字符串进行加密时,无论密码的长度为多少,经过加密后得到的hash值长度都是相同的。
- 当传入的字符串密码(明文)相同的话,经过同一个hash算法得到的hash值(密文)会是相同的。 ===>> 可以用于进行文件的校验
- 通过hash算法得到的hash值(密文),是不能进行反解的,也就是说不能通过密文来反推用户的明文密码的。 ===>> 可以用来对用户的明文密码进行加密,防止被盗号等。
二,密码加密
通过调用hashlib模块下的hash算法就可以将传入的字符串进行相应hash算法的明文加密,得到一串hash值,也就是一串经过hash算法之后得到的密文。将该密文写入文件中,然后当用户登录时,在文件中比对密文来判断是否登录成功。
为了方便理解,我们可以将hashlib中的hash算法理解为一个工厂,用户传入的明文为原材料,而后输出的密文就是该工厂经过加工的产品。
1,代码演示:
import hashlib
passwords1 = hashlib.sha256() # 调用sha256的hash算法
passwords1.update('liming666'.encode('utf-8')) # 传入密码1
print('密码1:' + passwords1.hexdigest())
passwords2 = hashlib.sha256()
passwords2.update('@liming666'.encode('utf-8')) # 传入密码2
print('密码2:' + passwords2.hexdigest())
密码1:b474b63a855469a9f8d4ff63bba2c7b9577a50c1456439133cb3fedf63e4a642
密码2:9c8f8252922d5baf7dc12b0e0d6be09df185aa2b22686897be89ceda97f5db0f
请按任意键继续. . .
可以看到,这里传入的密码1跟密码2 的长度是不一样的,但是经过同一种hash算法转化成密文之后密文的长度是一样长的,所以经过同一中hash算法,不管传入的明文密码的长度是多长,转换后的密文长度都是一样长的。
2,传入的明文长度不同,但是得到的密文长度一样长。
import hashlib
passwords1 = hashlib.sha256() # 调用sha256的hash算法
passwords1.update('liming666'.encode('utf-8')) # 传入密码1
print('密码1:' + passwords1.hexdigest())
passwords2 = hashlib.sha224() # 注意:这里换了一种hash算法。
passwords2.update('@liming666'.encode('utf-8')) # 传入密码2
print('密码2:' + passwords2.hexdigest())
密码1:b474b63a855469a9f8d4ff63bba2c7b9577a50c1456439133cb3fedf63e4a642
密码2:8b0a4e58f5120ae85d772d5301edd67c36aeb9192a0c2a9b7cfbbce9
请按任意键继续. . .
通过结果可以看到,经过不同的hash算法得到的密文长度是不一样的。所以不同的hash算法会得到不同的hash值,也就是密文不同。
需要注意的是,通过hashlib.update()函数,在为其传参的时候可以不用一次性的全部将明文传过去,可以分步传值。
3,分步传明文字符串,得到的密文是一样的。
import hashlib
passwords1 = hashlib.sha256() # 调用sha256的hash算法
passwords1.update('@'.encode('utf-8')) # 分步传值
passwords1.update('liming'.encode('utf-8'))
passwords1.update('666'.encode('utf-8'))
print('密码:' + passwords1.hexdigest())
passwords2 = hashlib.sha256()
passwords2.update('@liming666'.encode('utf-8')) # 一次性全部传过去
print('密码:' + passwords2.hexdigest())
密码:9c8f8252922d5baf7dc12b0e0d6be09df185aa2b22686897be89ceda97f5db0f
密码:9c8f8252922d5baf7dc12b0e0d6be09df185aa2b22686897be89ceda97f5db0f
可以看到, 即使分步传,最后得到的密文依旧是同样的。
4,小小的注意点
如果足够细心的话,可能一些读者可能注意到了,在实例3的代码中,调用了两次hashlib.sha256(),也就是这里有passwords1和passwords2,所以可能存在疑问,为什么不能直接调用一次hashlib.sha256() 呢?当只调用一次的话,其实也会得到一串hash值,但是并不是想要的明文转换成的密文。
代码演示一下吧:
import hashlib
passwords1 = hashlib.sha256() # 调用sha256的hash算法
passwords1.update('liming'.encode('utf-8'))
passwords1.update('666'.encode('utf-8'))
passwords1.update('@liming666'.encode('utf-8')) # 一次性全部传过去
print('密码:' + passwords1.hexdigest())
passwords2 = hashlib.sha256()
passwords2.update('liming666@liming666'.encode('utf-8'))
print('密码:' + passwords2.hexdigest())
密码:3a9568d16ee8080a265eab8f73750b3771477b25e0bc97313a0a803109ccf084
密码:3a9568d16ee8080a265eab8f73750b3771477b25e0bc97313a0a803109ccf084
请按任意键继续. . .
可以看到的是两种转化后密文是一样的,也就是说当向hash算法中通过update()函数向这个工厂中送原材料时,这些原材料会一直存在在工厂中,然后一起被加密。
三,密码撞库
密码撞库,简单理解就是创建一个猜测可能是明文密码的字典,然后将这些明文转换成密文,然后跟截获的密文进行比对,但密文相同的话那么通过字典就知道了对应的明文密码。当然这些撞库的前提是知道了明文加密的方式,也就是知道了明文加密的hash算法。
代码演示:
import hashlib
passwords_hash = 'cd1066bd6328de760c77b3ad975a4bbaa93462746f69eca165969fbc765f0169' # 截获的密文
passwd = ['liming666','@liming666','liming@666','liminglovexiaohong666','liming+qq'] # 猜测的可能是正确的明文密码
dic = {}
for value in passwd:
res = hashlib.sha256(value.encode('utf-8'))
dic[value] = res.hexdigest()
# 此时字典dic中key = 明文,value = 密文
for k,v in dic.items():
if v == passwords_hash:
print('撞库成功')
print("明文密码为%s"%k)
break
else:
print("尝试下一个明文密码")
尝试下一个明文密码
尝试下一个明文密码
尝试下一个明文密码
尝试下一个明文密码
撞库成功
明文密码为liming+qq
请按任意键继续. . .
这样就完成了简单的撞库实例。
四,密码加‘盐 ’
我们知道没有绝对安全的密码,所以我们所能做的就是增大对方破解明文密码的成本。就相当于一个用户的账户只有一块钱,结果一个人却花了10天来破解密文密码,连时间成本都不够,这样别人也懒得破解密码了。那么回到话题上,密码加盐,简单来说就是为用户在注册密码的时候增加一点东西进去,这样就可以增大别人进行密码撞库的成本。这样除非破解者知道加的‘盐’是什么才能增大破解的成功率,但是设计者添加的‘盐’,破解者应该是很难猜到的。
# 简单的密码加盐
import hashlib
passwords = hashlib.sha256('天王'.encode('utf-8'))
passwords.update('liming666'.encode('utf-8'))
passwords.update('盖地虎'.encode('utf-8'))
print(passwords.hexdigest())
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
passwords1 = hashlib.sha256()
passwords1.update("天王liming666盖地虎".encode('utf-8'))
print(passwords1.hexdigest())
d6f759a30f9c875caa58f7a341cce140245d6eea762ef1d1da75f4caec006e66
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
d6f759a30f9c875caa58f7a341cce140245d6eea762ef1d1da75f4caec006e66
这样经过加盐之后,即使被截获了密文密码,但是不知道加的‘盐’是什么,依旧是无法进行破解的。即使知道了‘盐’是什么,依旧会增加撞库的成本。