一、哈希算法hashlib模块
1、何为hash?
简单来说hash算法是一种摘要算法,又称散列算法,它对数据进行运算后得到一串hash值!如果各位有兴趣,网上有很多文章非常详细地介绍hash!
2、为何用hash?
先来说说hash的几个特点:
2.1、不可逆性
即使知道hash值,但你无法根据hash值反推算出原数据!根据这个特性,hash算法极其适合用于加密数据!
2.2、定长输出
无论要计算的数据有多大,输出的hash值长度永远不变!
2.3、雪崩效应
大家知道在雪山上,因为雪花结构特点,大声呼喊时极容易引起雪崩!同理,hash算法只要数据有细微改变,计算出来的hash也是不一样的!根据这个特点,它非常适合用于校验数据的完整性,只要改过一个字符,计算出来的结果都是不一样的!
2.4、确定性
同一种算法,计算同样的数据,得到的结果一定是一样的!
3、如何用hash?
以前Python2有MD5、SHA两个模块,Python出了个hashlib把它们都涵盖了,目前涵盖有以下算法:
- md5
- sha1
- sha224
- sha256
- sha384
- sha512
以上算法按照复杂程度自上而下为简单至复杂,当然越复杂也计算得越慢,digest摘要长度也越长!
3.1、计算hash值
md5_value = hashlib.md5() # 其它算法仅需要在这里把md5换成对应的sha1 sha224 sha256 sha384 sha512即可
md5_value.update('hello'.encode('utf-8')) # 此处拿到的是一个hash的对象,需要用hexdigest来获取hash值
print(md5_value)
print(md5_value.hexdigest())
# 执行得到结果
<md5 HASH object @ 0x01653E50> # 得到的是HASH对象
5d41402abc4b2a76b9719d911017c592 # 解开后真正的hash值
下面来比较一下各算法hash长度,数据统一为"hello,world!"
算法 | hash值 |
---|---|
MD5 | c0e84e870874dd37ed0d164c7986f03a |
SHA1 | 4518135c05e0706c0a34168996517bb3f28d94b5 |
SHA224 | 8ca8306359700b64b25a070da3c042dc8fa6a885427580d2b6d774f4 |
SHA256 | ec1e0bd875226943ad0e8877bdba4ca449c4cb8591a5363921c9f1ee20084c34 |
SHA384 | ceff8fdf21cc4e0f5217f7b674af88e5337636728d0d0b87acc28923a206d3a975443197253ceb306a3ff9b8e83f3c5a |
SHA512 | fa9edcfdaab7a4165f8d2593f04077d46aca957493e7e181ca479582d519a299d967305294d5d46fb5e0158240441b94cd96510c2311bdc86870e5ebf3efe60c |
4、密码应用hash
前面说过hash算法具有不可逆性,适合用于账号密码的存放,hash值明显就比明文密码比如"123456"这种强!但是回头想想,假设存放口令的数据库等落入了不法之徒手里!因为很多人喜欢设置简单密码,比如生日,123456等等简单密码,这时候不法之徒们虽然看到的是一串串hash值,但是他们只需要提前将一些常见的密码组合计算出hash值来一一进行对比,那么你的简单密码很有可能就被碰撞出来!
针对这种情况,我们可以在口令存入的那一刻给它加点东西,这样它计算出来的hash一定跟原文hash值不一样,这样就算黑客猜对了正确密码的hash值也是错误的!
passwd = input('请输入需要设置的密码:').__str__()
print('原hash值:', hashlib.md5(passwd.encode('utf-8')).hexdigest())
new_hash = passwd + 'haha'
print('新hash值:', hashlib.md5(new_hash.encode('utf-8')).hexdigest())
# 执行得到结果
请输入需要设置的密码:hello
原hash值: 5d41402abc4b2a76b9719d911017c592
新hash值: ab540ca02784f1e2f0fb8e1d2d1d92a9
二、随机值模块random
2.1、0到1间随机浮点数
>>> import random
>>> random.random()
0.875048525289821
2.2、指定范围随机浮点数
>>> random.uniform(2,6)
4.127460087546064
2.3、随机整数范围
此函数为开区间,即包括指定的数字范围,如下面的3到6,也包括3和6!
>>> random.randint(3,6)
4
>>> random.randint(3,6)
6
2.4、指定范围随机数
这个随机整数跟上面的随机整数区别是,这个不包括范围末尾数字本身,如下所示不包括范围数字6!可以说是顾头不顾尾!
>>> random.randrange(3,6)
5
>>> random.randrange(3,6)
4
>>> random.randrange(3,6)
3
>>> random.randrange(3,6)
3
2.5、随机抽取列表
从指定的列表中随机抽取一个元素
>>> random.choice([33,66,77,88])
33
>>> random.choice([33,66,77,88])
77
>>> random.choice([33,66,77,88])
88
2.6、列表任意组合随机数
sample必须要给定两个参数,其中第一个为容器数据类型,第二个为组合次数!如下所示:
>>> random.sample(range(0, 9), 4)
[7, 4, 3, 2]
>>> random.sample(range(0, 9), 4)
[7, 0, 4, 6]
2.7、random应用
random多被用于验证码!
2.7.1、纯数字验证码
import random
random_list = ''
for i in range(6): #循环次数即几位数的验证码,这里是六位整数验证码
str_number = str(random.randint(0, 9)) #将随机取得的int转换为str,因为int无法拼接
random_list += str_number #str一个一个地拼接到列表
print(random_list)
# 执行得到结果
259853
2.7.2、复杂验证码
import random
# chr函数可以转换十进制数字为ASCII表中的字符,小写字母a-z对应97-122
# old与chr相反,将字母转换为十进制数字
# join函数可以按照指定格式拼接容器数据类型,str.join(sequence),str是连接符,sequence是数据序列
random_list = []
for i in range(6):
letters = chr(random.randint(97, 122)) # 利用chr函数转换整数得到随机字母
str_number = str(random.randint(0, 9)) # 将随机int转换为str,因为int无法拼接
random_choice = random.choice([letters, str_number]) #将字母与数字组合起来
random_list.append(random_choice) # 追加到列表
print(''.join(random_list)) # 拼接字符串
# 执行得到结果
9jbf60