hashlib 与 hmac 模块

一.引入

1.什么是算法

  • 算法就是高效解决问题的方法
  • 一种算法就是用来解决一种特定问题的
比如从10000个从小到大排列且不连续数字里找出8654
普通方法就是用眼瞅,从左到右
运气好瞅一次,运气不好瞅一万次
于是就有了二分法,取出中间的值
左边的值一定比中间的值小
右边的值一定比中间的值大
于是找到8654所用的时间大大缩短

2.hash哈希算法

可以把把文本内容/一串字符计算成一串 hash

一串内容---->"hash"算法---->"hash"
  • md5

  • sha512

  • sha256

3.hash值的三大特点

  • 传入的内容一样, 采用的 hash 算法一样, 得到的 hash 值也一定一样
  • hash 不可逆推, 不能通过 hash 值反推出明文
  • hash 值的长度取决于采用的 hash 算法, 与传入的内容多少无关

4.哈希的应用

  • 结合特点 12 可以用于加密
  • 结合特点 13 可以用于文件完整性校验
再网页上下载文件进度条100%后会卡一小些时间
其实就是在进行"hash"的校验

5.密码加盐

  • 客户端向服务端提交密码会在客户端先通过算法加密
  • 而服务端存有加密后的密码, 直接比对进行校验
  • 但是这还是不够安全的,高技术的黑客可以拿着密文密码进行撞库或者写客户端直接提交截获到的密文
  • 于是就出现了密码加盐的概念
⛅密码加盐相当于暗号,只有设置者知道
⛅示范:
	正常密码: 123456
	加盐密码: 派大星123456海绵宝宝
	    或者:123456
⛅加盐之后计算出来的"hash"是完全不一样的
⛅想要撞库的人就必须要猜到使用的算法和加的盐

一.hashlib 模块介绍

1.什么是 hashlib 模块

  • hashlibPython的内置模块
  • 它为我们提供了多种安全的摘要方法

2.hashlib 模块的作用

  • 目前在大部分操作系统下, hashlib模块支持md5(),sha1(), sha224(), sha256(), sha384(), sha512(), blake2b()…等多种hash构造方法
  • 这些构造方法在使用上通用, 返回带有同样接口的hash对象, 差别只在于构造方法的选择, 也就是对算法的选择
  • 得到对象后可以使用通用的update()方法将bytes类型的数据添加到对象里,最后通过digest()(bytes摘要) 或者hexdigest()(十六进制摘要) 方法获得当前的摘要
🍓 "hashlib"模块所支持的算法
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
                      'blake2b', 'blake2s',
                      'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
                      'shake_128', 'shake_256')

ps : update( )方法现在只接受bytes类型的数据,不接收str类型

二.hashlib 模块的使用

1.放入原材料, 得到摘要

import hashlib

# m = hashlib.sha512()
m = hashlib.md5()  # 还有其他算法"sha256()"等等
m.update("helloword".encode("utf-8"))
res = m.hexdigest()
print(type(res))  # <class 'str'>
print(res)        # 59284aa85709ddaf3bd246030060f6a2

2.将原材料分多次 update( )

  • 把一段很长的数据update多次, 与一次update这段长度的数据,得到的结果一样, 但是update多次为校验大文件提供了可能
import hashlib

# m = hashlib.sha512()
m = hashlib.md5()  # 还有其他算法"sha256()"等等
m.update("he".encode("utf-8"))
m.update("llo".encode("utf-8"))
m.update("word".encode("utf-8"))
res = m.hexdigest()
print(res)        # 59284aa85709ddaf3bd246030060f6a2

3.密码加盐

  • 以上加密算法虽然非常安全, 但有时候存在缺陷, 黑客通过撞库可以反解, 所以, 有必要对加密算法中添加自定义key再来做加密
import hashlib

🍓没加盐
m = hashlib.sha256()
m.update("helloword".encode("utf-8"))
res = m.hexdigest()
print(res)  # 0b322d15ea034793a8646baa1744ffacbdf7f959b66c68970f032c4ac8b9c8cb

🍓密码加盐
salt = "我是盐"
m = hashlib.sha256()
m.update("helloword".encode("utf-8"))
m.update(salt.encode("utf-8"))
res = m.hexdigest()
print(res)  # c3527c3cf2592303ed2e616772c6f5409e7ab4a40c2f49cb8c16647abc0048ac

可以发现两种结果完全不同, 加的盐只有你自己知道, 那么被破解的几率就大大降低了

三.hmac 模块

1.什么是 hmac 模块

  • hmac 模块也是 Python 的内置模块
  • 它内部采用了 key 对应 内容 的方式进行进一步的加密方式

2.保证 hmac 结果一致

  • 必须保证 hmac.new( ) 括号内指定的初始 key 相同
  • 无论 update 多少次, 校验的内容累加一起必须一样

3.hmac 的使用

  • 加密内容一次 update
import hmac

h = hmac.new("init_key".encode("utf-8"),digestmod="md5")
h.update("helloword".encode("utf-8"))
res = h.hexdigest()
print(res)  # 7c221a51ee6e0d36a1a8b07d7948bc0c
  • 加密内容多次 update
h = hmac.new("init_key".encode("utf-8"),digestmod="md5")
h.update("he".encode("utf-8"))
h.update("llo".encode("utf-8"))
h.update("word".encode("utf-8"))
res = h.hexdigest()
print(res)  # 7c221a51ee6e0d36a1a8b07d7948bc0c

我們可以发现摘要值结果一样

  • 将初始 key 更换, 加密内容不变
h = hmac.new("neq_key".encode("utf-8"),digestmod="md5")
h.update("helloword".encode("utf-8"))
res = h.hexdigest()
print(res)  # 200e7722b5842e83851955e20dabb6e8

可以发现摘要值已经变化了

小结 :

​ 使用hmac算法比标准hash算法更安全,因为针对相同的加密内容,不同的key会产生不同的hash

三.暴力破解

006APoFYjw1f90i0ph40lg3046046gmq

什么是暴力破解? 其实就是乱猜. 暴力破解其实是通过循环的方式进行对比, 我们都知道加密算法是不可逆的, 比如 MD5 算法, 那么网上那些所谓的 MD5 解密网站是怎么做到的呢? 其实使用的就是这种原理.

撞库的原理也差不多 : 简单来说,撞库就是黑客利用已经泄露的账号密码,去其他网站或应用程序中尝试登录的行为。撞库主要利用的是人们在多个平台使用相同账号密码的行为习惯

import hashlib

m = hashlib.md5()
m.update("123".encode("utf-8"))
print(m.hexdigest())  # 202cb962ac59075b964b07152d234b70

就比如我们通过 MD5 算法加密一段字符串 “123” 得到的密文是 “202cb962ac59075b964b07152d234b70” , 我们是无法看懂或者是解密的, 那网上的 MD5 是怎么做到的, 其实他们就是将一些简单的密码 : 123,abc, 123456, abc123,…等等这种比较简单的低级密码都进行加密的一遍, 然后放在他们的数据库里边, 你在使用的时候恰巧就对比到一样的密文, 这就是 MD5 暴力破解

image-20210112155001593

稍微加一个@符号试试

import hashlib

m = hashlib.md5()
m.update("1234@".encode("utf-8"))
print(m.hexdigest())  # 2119eb59afc81b22cf8a4298047f9723

image-20210112155428264

所以我们只要把密码设置复杂一点就不用怕MD5暴力破解了

ps : 2004年8月17日的美国加州圣巴巴拉,正在召开的国际密码学会议, 来自山东大学的王小云教授做了破译MD5、HAVAL-128、 MD4和RIPEMD算法的报告, 当时引发了密码学界的轩然大波, 但好像MD5算法团队又对MD5算法进行了修改, 到现在为止还是比较安全的

四.模拟密文密码撞库

006r3PQBjw1f90iz2z78fg3046046aca

我们来模拟一下密码撞库

import hashlib,shelve

with shelve.open(r"./passed.txt")as f:
    while True:
        strs = input("输入明文进行密文入库(q退出)>>").strip()
        if strs == "q":break
        m = hashlib.md5()
        m.update(strs.encode("utf-8"))
        res = m.hexdigest()
        f[strs] = res

with shelve.open(r"./passed.txt")as f1:
    while True:
        passwd_md5 = input("输入密文进行解密(q退出)>>").strip()
        if passwd_md5 == "q": break
        for k,v in f1.items():
            if passwd_md5 == v:
                print(f"明文密码 : {k}")
                break
        else:
            print("解密不成功, 我们会继续努力")

演示效果:

image-20210112171948179

五.模拟网上下载大文件进行MD5值计算的快速方式

假设一个 10G 的大文件, 要计算整个文件的 MD5 值会比较慢, 那么我们可以截取固定位置的字节来进行校验, 这样就快了很多, 甚至可以加盐对比, 这样一来就可以防止他们从中间恶意串改文件, 也可以加快速度

import os,hashlib,shutil

def auth(path):
    file_size = os.path.getsize(path)
    with open(path,"rb")as f:
        f.seek(0)                  # 指针在开头
        res1 = f.read(3)           # 取三个字节
        f.seek(file_size//10,0)    # 指针在十分之一处
        res2 = f.read(3)           # 取三个字节
        m = hashlib.md5()
        m.update(str(res1+res2).encode("utf-8"))
        return m.hexdigest()       # 六个字节加密后返回

hash1 = auth(r"D:\Python16每日视频\day05\视频\08 文件处理.mp4")
print(hash1)  # bb0007474f0505b5ff24332733cf0ea5

# 拷贝文件模拟文件下载,改变文件和路径
shutil.copyfile(r"D:\Python16每日视频\day05\视频\08 文件处理.mp4","./aa.txt")

hash2 = auth("./aa.txt")
print(hash2)  # bb0007474f0505b5ff24332733cf0ea5

由上可知, 拷贝之后的文件与源文件得到的MD5摘要完全相同(这里我只演示了两处截取字节, 也没有加盐), 说明校验文件成功, 文件完整

ps : 我们下载一个文件的时候经常在 90% 或者 100% 的时候卡住一段时间, 其实这就是在进行hash值的校验, 如果校验不成功甚至会重新下载

v2-056aa23c988d01217d6e746429e30632_720w

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给你骨质唱疏松

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值