内置模块之hashlib

hashlib模块

  hashlib模块是一个内部有摘要算法的模块,而且内部可以给我们提供不止一种摘要算法。

  为什么需要摘要算法?

  由于数据的不安全性,为了保证用户的信息的绝对安全,所有敏感的数据都不应该用明文传输,而应该经过适当的处理,通过密文来存储。摘要算法就是通过对任意长度的内容经过计算,转换为一个定长的16进制的字符串,目的是保证该文件没有被篡改过。摘要算法,之所以能够做到这点,是因为算法都是不可逆的。

  为什么需要hashlib?

  1.因为不同的字符串通过摘要算法得到的密码总是不同的,相同的算法相同的字符串总是相同的。

  2.在不同的编程语言,不同的环境(操作系统,版本,时间),都是一致的,不存在差异。


hashlib模块的使用

  hashlib模块提供了多种摘要算法:

    md5算法: 定长32位  16进制(应用最广发的摘要算法)

    sha系统算法: 定长40位  

      #sha算法要比MD5算法更加复杂,且sha N数值越大,算法越复杂,耗时越久,结果越长,但也更安全

#hashlib模块md5摘要算法的使用
name = 'alex'
password = 'alex3714'               

#1.首先,需要先实例化一个md5的对象,一个对象只加密一个数据
md5_obj = hashlib.md5() 
#2. update()方法,把需要进行MD5的对象放入
md5_obj.update(password.encode('utf-8'))
#3.通过hexdigest(),得到摘要算法之后的密文
md5_password = md5_obj.hexdigest()
print(md5_password)
print(len(md5_password))                 #md5算法,定长32位
>>>
aee949757a2e698417463d47acac93df
32
# 使用sha摘要算法
name = 'alex'
password = 'alex3714'

#操作与md5如出一辙,先创建对象,通过update加密,在通过hexdigest取值
sha_obj = hashlib.sha1()
sha_obj.update(password.encode('utf-8'))
sha_password = sha_obj.hexdigest()
print(sha_password)
print(len(sha_password))          #sha1算法定长40位
>>>
8a003668a9c990f15148f9e4046e1410781533b6
40     

hashlib的应用  

  • 用户登录的验证
name    | password
--------+----------
hehehe | hehehe1994

  有一个用户hehehe,密码为hehehe1994,如果密码就这样用明文存储,如果数据库被黑客侵入,那么密码就毫无保留的暴露给了黑客。所以这时候就需要用到摘要,在数据库中,存储密码的摘要信息。每次登陆的时候,在做摘要信息的比对。

username | password
---------+---------------------------------
michael  |69d5dd8a4651f8c77adc140c53469479

   所以每次登陆的时候,便需要进行密码信息的摘要比对。

def get_md5_pws(s):
    md5_obj = hashlib.md5()
    md5_obj.update(s.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret

username = input('username>>>:').strip()
password = input('password>>>:').strip()

with open('userinfo',encoding='utf-8') as f:
    for line in f:
        usr,pwd = line.strip().split('|')
        if username == usr and get_md5_pws(password) == pwd:
            print('登录成功')
            break
    else:
        print('登录失败')

  通过摘要算法的手段,虽然密码是用密文的形式存储了,但是在现在的攻击手段中,有一种叫做"撞库"的手段,就是通过一个存储着大量密码与md5后的摘要对应的关系,再一一进行匹配,如果摘要信息一致,便能够反推出密码,因为同一种算法的同一个字符串,结果总是不变的。那么,有什么方法能够防止撞库?那就通过加盐值得手段(1.固定盐值  2.更好的方法:动态加盐

  何为盐值(salt),其实就是给原数据+一段指定的字符串,这样得到的MD5值就会发生变化。只要颜值不被黑客知道,那么就很难反向推出原数据。

#加盐的md5算法,采用固定盐值(盐值:salt)
username = 'hehehe'
password = 'hehehe1994'
md5_obj = hashlib.md5('salt'.encode('utf-8'))       #加盐
md5_obj.update('alex3714'.encode('utf-8'))
ret = md5_obj.hexdigest()
print(ret)


#动态加盐,通过把用户的唯一标识作为盐值,例如每个用户的用户名都是唯一
username = 'hehehe'
password = 'hehehe1994'
md5_obj = hashlib.md5(username.encode('utf-8'))       #动态加盐
md5_obj.update('alex3714'.encode('utf-8'))
ret = md5_obj.hexdigest()
print(ret)
  • 文件一致性的校验

  给一个文件中的所有内容进行摘要算法,得到一个md5结果。此时,我们可以体验到md5摘要算法的神奇的地方,对于同一个字符串,不管把他拆开多少段,最终得到的md5值都是一样。

# 同一个字符串,不管拆开多少段,最终的md5都是一样的。

slogan= 'hello,python'
md5_obj1 = hashlib.md5()
md5_obj1.update(slogan.encode('utf-8'))
ret1 = md5_obj1.hexdigest()
print(ret1)
>>>
15ac32041ff74c93c1842b152df7519e

md5_obj2 = hashlib.md5()
md5_obj2.update('hello,'.encode('utf-8'))
md5_obj2.update('python'.encode('utf-8'))
ret2 = md5_obj2.hexdigest()
print(ret2)
>>>
15ac32041ff74c93c1842b152df7519e

  所以,对文件进行一致性校验。

def get_file_md5(file_path):
    md5_obj = hashlib.md5()
    with open(file_path,encoding='utf-8') as f:
        for line in f:
            md5_obj.update(line.encode('utf-8'))
    ret = md5_obj.hexdigest()
    return ret
  • 对视频进行一致性校验

   一般是视频格式的文件/网络传输的文件,都是二进制的bytes类型。此时没有行的概念,该怎么做?此时,可以设置一个buffer,每次都读取相同长度的buffer.

#设置一个buffer,每次都通过f.read(buffer)读取定长的数据。
def get_video_md5(file_path,buffer=1024):
    file_size = os.path.getsize(file_path)
    md5_obj = hashlib.md5()
    with open(file_path, 'rb') as f:
        while file_size:
            content = f.read(buffer)
            file_size-= len(content)
            md5_obj.update(content)
    return md5_obj.hexdigest()

  

  

原文地址:https://www.cnblogs.com/hebbhao/p/9599181.html