hashlib模块

seekerhit 2020-02-15

hashlib模块

hashlib模块是一个摘要算法模块,能够把一个字符串数据类型的变量转换成一个定长的、密文的字符串,字符串里的每一个字符都是一个十六进制数。

一、hashlib模块算法的共同特点

  • 对于同一个字符串,不管字符串有多长,只要是相同的,无论在任何环境下,多少次执行,在任何语言中使用相同的算法/相同的手段的结果永远是相同的。
  • 只要不是相同的字符串,得到的结果一定不相同。

二、md5算法

  • 优点:32个字符,相对于sha1算法的40个字符,md5算法普及率更高,计算速度更快
  • 缺点:相对于sha1算法,md5算法没有sha1算法安全。不够安全不是因为算法本身,而是因为速度快,使用的人多,那么存在撞库的风险也就越大。
  • 算法流程:
    • 创建md5对象:md5_obj = hashlib.md5()
    • 更新对象:md5_obj.update(str_obj.encode(‘utf-8‘))
    • 生成密文结果:md5_obj.hexdigest()
    • 打印

三、sha1算法

  • 优点:40个字符,相对于md5算法更加安全
  • 缺点:速度比md5更慢
  • 算法流程:
    • 创建md5对象:sha1_obj = hashlib.sha1()
    • 更新对象:sha1_obj.update(str_obj.encode(‘utf-8‘))
    • 生成密文结果:sha1_obj.hexdigest()
    • 打印
import hashlib
# md5是一个算法
str = 'lizhen122343254'
md5_obj = hashlib.md5()
md5_obj.update(str.encode('utf-8'))
ret = md5_obj.hexdigest()
print(ret, len(ret), type(ret))
# sha1算法
sha1_obj = hashlib.sha1()
sha1_obj.update(str.encode('utf-8'))
ret1 = sha1_obj.hexdigest()
print(ret1, len(ret1), type(ret1))

'''
9312639e4e17d01b0fc88d6a84e8cff3 32 <class 'str'>
06af75e90a56b268582388f99526c73faabca62e 40 <class 'str'>
'''

撞库:加密摘要算法主要用于处理存入数据库中的非常重要信息,例如:密码,当注册密码后,通过算法程序对注册的密码进行加密计算生成一个加密的唯一字符串存在数据库中,注意:不是把密码直接存在数据库。当登陆的时候,加密算法根据输入的密码生成加密字符串,把新生成的加密字符串与数据库中存入的唯一加密字符串比对,如果相等则允许登陆,如果不想等则不允许登陆,这是保护信息安全的重要一环。虽然加密算法不可逆,一旦加密就不可能通过加密字符串推出原有字符串,但是很多的不怀好意的人,专门创建数据库,存储自己编写的字符串生成的加密字符串,把这些加密字符串和别人数据库中的加密字符串比对,寻找相等的加密字符串,从而拿到原有字符串的内容,这个被称为撞库。

四、登陆的密文验证(针对撞库问题的解决办法)逐渐进阶

  • 最初级的加密即是上边直接对一个字符串进行加密,这种加密通过撞库简单的常用的字符串很容易被破解
  • 静态加盐:针对初级加密中的问题,进一步的解决办法是加盐,即在创建算法对象的时候直接加入固定字符串,并对字符串进行编码,然后再执行update()和hexdigest()方法,最后得到加盐后的加密字符串,这个字符串和单纯的一个字符串的加密字符传不一样,如果攻击者不知道加的盐是什么,密码就是安全的。但是如果攻击者找到了加的盐的内容,整个数据库都存在风险。
  • 动态加盐:既然上边静态加盐也不安全,那么可以把盐换成动态的,即username为盐,password为需要加密的字符串,username和password完全相同的几率极小,这样的话账号就是安全的。

    创建安全防护的时候必须用动态加盐的方式,前两种为推导的过程。

# 动态加盐
import sys
username = sys.argv[1]
pwd = sys.argv[2]
# 这里用的是sys模块中的argv交互,也可以使用input
def create_md5(username, pwd):
    md5_obj = hashlib.md5(username.encode('utf-8'))
    md5_obj.update(pwd.encode('utf-8'))
    password = md5_obj.hexdigest()
    return password

md5_password = create_md5(username, pwd)
if md5_password == '431149301c8792c1ab4c40b783d37100' and username ==username:
    print('登陆成功')
else:
    print('登陆失败')

五、文件的一致性校验问题

文件的一致性认证使用的也是hashlib模块中的加密算法,把‘文件句柄.read(每次读取字节)’作为update的参数来使用,其他的逻辑和和普通的算法一样。

需要注意的是:

  • byte文件在read()后不需要使用encode(‘utf-8‘)编码,json格式文件需要在read()后添加encode(‘utf-8‘)编码
  • 一次性从文件中读取内容的update和分批次、多次从同一文件中连续读取所有内容的update效果是完全一样的,得到的密文字符串也是完全一样的。
import os
import hashlib
'''创建一个函数读取文件并进行文件一致性校验'''
def sha1_num(path, bytes_num=100):
    size_num = 0
    # 字节数
    file_size = os.path.getsize(path)
    # os.path.getsize(path)获取文件总的字节数
    sha1_obj = hashlib.sha1()
    # 创建sha1加密对象
    with open(path, 'rb') as f:
        while size_num <= file_size:
        # 当字节数小于等于总的字节数时执行下边操作
            sha1_obj.update(f.read(bytes_num))
            # hashlib模块中文章一次读取update的结果和分段读取update的结果是完全一样的
            size_num += bytes_num
            
        result = sha1_obj.hexdigest()
    return result

s1 = sha1_num('../第三方库/pickle_dump', bytes_num=10240000)
s2 = sha1_num('../pickle_dump', bytes_num=10240)
# 两个同样的文件,放在不同的路径下,判断文件的一致性
if s1 == s2:
    print(True)
    # 密文相等则文件具有一致性
else:
    print(False)

'''
True
'''

相关推荐

手机开发 / 0评论 2016-09-29