常用模块-随机和哈希
1 random 模块
该模块用于生成随机数
1.1 取随机数
import random
print(random.random()) #(0,1)----float 大于0且小于1之间的小数
print(random.randint(1,3)) #[1,3] 大于等于1且小于等于3之间的整数
print(random.randrange(1,3)) #[1,3) 大于等于1且小于3之间的整数
print(random.choice([1,'23',[4,5]])) #1或者23或者[4,5]
print(random.sample([1,'23',[4,5]],2)) #列表元素任意2个组合 返回列表
print(random.uniform(1,3)) #大于等于1小于3的小数,如1.927109612082716
1.2 打乱列表 shuffle
import random
item=[1,3,5,7,9]
random.shuffle(item) #打乱item的顺序,相当于"洗牌"
print(item)
1.3 练习
生成随机验证码 随机字母和数字
import random
def make_code(n):
res=''
for i in range(n):
s1=chr(random.randint(65,90))
s2=str(random.randint(0,9))
res+=random.choice([s1,s2])
return res
print(make_code(9))
2 hashlib 模块
Python的hashlib提供了常见的哈希算法,如MD5,SHA1等等
2.1 什么是哈希(hash)
哈希算法又称摘要算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)
每个字符串都已通过哈希算法生成固定且唯一的哈希值,字符串发生改变,对应的哈希值也会改变
哈希值的特点如下
- 只要传入的内容一样,得到的hash值必然一样
- 不能由hash值返解成内容,hash运算时单向的,不可逆
- 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
2.2 hashlib模块中的哈希算法
hashlib模块主要提供了如下哈希方法
md5
32位16进制数 128位2进制数sha1
40位16进制数 160位2进制数sha224
56位16进制数 224位2进制数sha256
64位16进制数 256位2进制数sha384
96位16进制数 384位2进制数sha512
128位16进制数 512位2进制数
2.3 hashlib的使用
import hashlib
md5 = hashlib.md5('123456'.encode('utf-8'))
print(md5.hexdigest())
import hashlib
md5 = hashlib.md5()
md5.update('hello dandan'.encode('utf-8'))
print(md5.hexdigest()) # 32087773681bb6ada67d151105d37e70
sha1 = hashlib.sha1()
sha1.update('hello dandan'.encode('utf-8'))
print(sha1.hexdigest()) # 31b1b4c4f4775f181aba04695dfabd502513d931
sha224 = hashlib.sha224()
sha224.update('hello dandan'.encode('utf-8'))
print(sha224.hexdigest()) #067e2173f2395ef76a069eccdf4279a19d0fb9fe078b722ad99afed7
sha256 = hashlib.sha256()
sha256.update('hello dandan'.encode('utf-8'))
print(sha256.hexdigest()) # a6c38c125bc355cd82ee59066b4f20c495f629d6cd61cfd1619dc5e2df18bc00
sha384 = hashlib.sha384()
sha384.update('hello dandan'.encode('utf-8'))
print(sha384.hexdigest()) # b88b7dfee7274331cd1cea7a74906979282e68c0e5a71cd2cd1515b0a0962440747cce6421e1a3e8a7b720dbb4a3dd60
sha512 = hashlib.sha512()
sha512.update('hello dandan'.encode('utf-8'))
print(sha512.hexdigest()) # 48c5392ea75b8270fff69a19ac7e6a47b12e88135967b7db1356e6bf5bd8ac21edb40b5ba933ce8f7cf5038d29f9b1a743bce9f896a236f4835d1f31c6ae4d0f
注意
调用多次update()
方法,实际上实在拼接字符串,如果需要加密的内容比较长,可以调用多次 update()
2.4 提高加密安全性
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
import hashlib
# ######## 256 ########
hash = hashlib.sha256('898oaFs09f'.encode('utf8'))
hash.update('alvin'.encode('utf8'))
print (hash.hexdigest())#e79e68f070cdedcfe63eaf1a2e92c83b4cfb1b5c6bc452d214c1b7e77cdfd1c7
以下模拟md5解密
import hashlib
md5 = hashlib.md5()
md5.update('123456'.encode('utf-8'))
print(md5.hexdigest())
passwds=[
'dan3714',
'dan1313',
'dan94139413',
'dan123456',
'123456dan',
'a123l',
'123456'
]
def make_passwd_dic(passwds):
dic={}
for passwd in passwds:
m=hashlib.md5()
m.update(passwd.encode('utf-8'))
dic[passwd]=m.hexdigest()
return dic
def break_code(cryptograph,passwd_dic):
for k,v in passwd_dic.items():
if v == cryptograph:
print('密码是 : \033[46m%s\033[0m' %k)
cryptograph = 'e10adc3949ba59abbe56e057f20f883e'
break_code(cryptograph, make_passwd_dic(passwds))
3 hmac 模块
前面提到为了加密更安全,我们再加密内容中,混入了Key, 实际上真正进行哈希运算的是 我设置的key+要加密的内容
, 这实际上就是Hmac算法 (Keyed-Hashing for Message Authentication)
hmac模块实现了标准的Hmac算法,采用Hmac替代我们自己生成Key
,可以使程序算法更标准化,也更安全。
import hmac
message = b'Hello, world!'
key = b'secret'
h = hmac.new(key, message, digestmod='MD5') #digestmod 默认值是 MD5
# 如果消息很长,可以多次调用h.update(msg)
h.hexdigest() 'fa4ee7d173f2d97ee79022d1a7355bcf'
import hmac
h1=hmac.new(b'dandan')
h1.update(b'hello')
h1.update(b'world')
print(h1.hexdigest())
h2=hmac.new(b'dandan')
h2.update(b'helloworld')
print(h2.hexdigest())
h3=hmac.new(b'dandan', b'helloworld')
print(h3.hexdigest())
4 哈希应用
4.1 存储密码
用户密码经过 哈希运算 后,将哈希值也就是密文 存入数据库
当验证的时候, 将用户输入的明文,计算哈希值,用哈希值与存储在数据库的密文进行比较
如此,即使数据库泄露也会将密码的明文泄露,此外,运维人员和数据库管理人员也无法读取到用户的密码明文
4.2 哈希碰撞
如果不同的输入得到了同一个哈希值,就发生了"哈希碰撞"(collision)
防止哈希碰撞的最有效方法,就是扩大哈希值的取值空间。
16个二进制位的哈希值,产生碰撞的可能性是 65536 分之一。也就是说,如果有65537个用户,就一定会产生碰撞。哈希值的长度扩大到32个二进制位,碰撞的可能性就会下降到 4,294,967,296 分之一。
更长的哈希值意味着更大的存储空间、更多的计算,将影响性能和成本。开发者必须做出抉择,在安全与成本之间找到平衡。