27、hash算法与random随机值

Python模块 / 2020-12-12

一、哈希算法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值
MD5c0e84e870874dd37ed0d164c7986f03a
SHA14518135c05e0706c0a34168996517bb3f28d94b5
SHA2248ca8306359700b64b25a070da3c042dc8fa6a885427580d2b6d774f4
SHA256ec1e0bd875226943ad0e8877bdba4ca449c4cb8591a5363921c9f1ee20084c34
SHA384ceff8fdf21cc4e0f5217f7b674af88e5337636728d0d0b87acc28923a206d3a975443197253ceb306a3ff9b8e83f3c5a
SHA512fa9edcfdaab7a4165f8d2593f04077d46aca957493e7e181ca479582d519a299d967305294d5d46fb5e0158240441b94cd96510c2311bdc86870e5ebf3efe60c

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
世间微尘里 独爱茶酒中