hashlib 这个模块是一堆加密算法的集合体,哈希算法的加密方式不止一种
https://www.cmd5.com/ md5解密
应用场景:在需要效验功能时使用
用户密码的 => 加密,解密
相关效验的 => 加密,解密
哈希算法也叫摘要算法,相同的数据始终得到相同的输出,不同的数据得到不同的输出。
(1)哈希将不可变的任意长度的数据,变成具有固定长度的唯一值
(2)字典的键和集合的值是通过哈希计算存储的,存储的数据是散列(无序)
场景: 网站密码加密
hashlib模块的加密原则是单向不可逆的
md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串
撞库破解
111222 => 00b7691d86d96aebd21dd9e138f90840 222333 => 00b7691d86d96aebd21dd9e138f90842
import hashlib import random # ### 基本语法 # (一)md5对象 # 1.创建md5对象 hs = hashlib.md5() # 2.把要加密的数据更新到对象中 [update => 把字节流更新到对象之后,进行加密] hs.update("111222".encode("utf-8")) # 3.获取十六进制的字符串 res = hs.hexdigest() print(res , len(res)) # 00b7691d86d96aebd21dd9e138f90840 # 加盐 (加key , 加一个关键字) hs = hashlib.md5("XBOYww_".encode()) hs.update("111222".encode()) res = hs.hexdigest() print(res) # 623e0e8d4ecabd638c36a5e40189ba8f # 动态加盐 res = str(random.randrange(100000,1000000)) hs = hashlib.md5(res.encode()) hs.update("111222".encode()) res = hs.hexdigest() print(res) # (二)sha系列算法 """无论是加盐 还是 加密密码,都需要数据类型为二进制字节流""" # hs = hashlib.sha1() # 结果是具有固定长度40位的十六进制字符串; hs = hashlib.sha512("XGIRLww_".encode()) # 结果是具有固定长度128位的十六进制字符串 hs.update("sha系列算法".encode()) res = hs.hexdigest() """20c2502d0e00bf8fe35ebfbf097049d1f070e7968f30ef3353ff33d311af50da6b3883bfb9ab411f9dc4cdcd2310b39f5815c6dc1c48cd138d07443a6bcdcd11 128""" print(res , len(res)) # (三)hmac加密算法 import hmac import os key = b"xdogaa_" msg = b"112233" # new(盐(字节流),密码(字节流) ) hm = hmac.new(key,msg) res = hm.hexdigest() """ eebe14b1c144092121236cb1e3da396a """ print(res , len(res)) # 动态加盐 """ os.urandom(位数) 返回随机的二进制字节流 res = os.urandom(10) print(res , len(res)) """ key = os.urandom(64) msg = b"112233" hm = hmac.new(key,msg) res = hm.hexdigest() print(res , len(res))View Code
""" mode = "r" fp.read(3) 3个字符 mode = "rb" fp.read(3) 3个字节 """ import hashlib import os # (1) 针对于小文件进行校验 def check_md5(filename): hs = hashlib.md5() with open(filename , mode="rb" ) as fp: hs.update(fp.read()) # return fp.read() 仅仅适用于小文件 return hs.hexdigest() res1 = check_md5("lianxi1.py") res2 = check_md5("lianxi2.py") print(res1 == res2) # (2) 针对于大文件进行校验 """update 可以分批次进行加密 等价于一次性加密的结果""" # update的使用 strvar = "今天是周五,明天自习" hs = hashlib.md5() hs.update(strvar.encode()) res1 = hs.hexdigest() print(res1) strvar2 = ",周一上午考试,小人射击+计算器" hs.update(strvar2.encode()) res2 = hs.hexdigest() print(res2) # 0163aa435c2eea52fac354ba7e6c84da strvar = "今天是周五,明天自习,周一上午考试,小人射击+计算器" hs2 = hashlib.md5() hs2.update(strvar.encode()) print(hs2.hexdigest()) # 0163aa435c2eea52fac354ba7e6c84da # 方法一 def check_md5(filename): hs = hashlib.md5() with open(filename,mode="rb") as fp: while True: # 最多读取5个字节 content = fp.read(5) # 判断读取的字节如果是空,终止循环 if content: hs.update(content) else: break return hs.hexdigest() res1 = check_md5("lianxi1.py") res2 = check_md5("lianxi2.py") print(res1 , res2) # 方法二 def check_md5(filename): hs = hashlib.md5() filesize = os.path.getsize(filename) print(filesize) with open(filename,mode="rb") as fp: # filesize 如果为空,循环终止; while filesize: content = fp.read(100) hs.update(content) # 减去实际读取的字节长度 filesize -= len(content) return hs.hexdigest() res1 = check_md5("lianxi1.py") res2 = check_md5("lianxi2.py") print(res1 , res2)View Code
肉眼根本看不出下面两个文件哪不一样
lianxi1.py文件
# ### hashlib """ 场景: 网站密码加密 hashlib模块的加密原则是单向不可逆的 md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串 """ # 撞库 """ 111222 => 00b7691d86d96aebd21dd9e138f90840 222333 => 00b7691d86d96aebd21dd9e138f90842 """ import hashlib import random # ### 基本语法 # (一)md5对象 # 1.创建md5对象 hs = hashlib.md5() # 2.把要加密的数据更新到对象中 [update => 把字节流更新到对象之后,进行加密] hs.update("111222".encode("utf-8")) # 3.获取十六进制的字符串 res = hs.hexdigest() print(res , len(res)) # 00b7691d86d96aebd21dd9e138f90840 # 加盐 (加key , 加一个关键字) hs = hashlib.md5("XBOYww_".encode()) hs.update("111222".encode()) res = hs.hexdigest() print(res) # 623e0e8d4ecabd638c36a5e40189ba8f # 动态加盐 res = str(random.randrange(100000,1000000)) hs = hashlib.md5(res.encode()) hs.update("111222".encode()) res = hs.hexdigest() print(res) # (二)sha系列算法 """无论是加盐 还是 加密密码,都需要数据类型为二进制字节流""" # hs = hashlib.sha1() # 结果是具有固定长度40位的十六进制字符串; hs = hashlib.sha512("XGIRLww_".encode()) # 结果是具有固定长度128位的十六进制字符串 hs.update("sha系列算法".encode()) res = hs.hexdigest() """20c2502d0e00bf8fe35ebfbf097049d1f070e7968f30ef3353ff33d311af50da6b3883bfb9ab411f9dc4cdcd2310b39f5815c6dc1c48cd138d07443a6bcdcd11 128""" print(res , len(res)) # (三)hmac加密算法 import hmac import os key = b"xdogaa_" msg = b"112233" # new(盐(字节流),密码(字节流) ) hm = hmac.new(key,msg) res = hm.hexdigest() """ eebe14b1c144092121236cb1e3da396a """ print(res , len(res)) # 动态加盐 """ os.urandom(位数) 返回随机的二进制字节流 res = os.urandom(10) print(res , len(res)) """ key = os.urandom(64) msg = b"112233" hm = hmac.new(key,msg) res = hm.hexdigest() print(res , len(res))View Code
lianxi2.py文件
# ### hashlib """ 场景: 网站密码加密 hashlib模块的加密原则是单向不可逆的 md5算法 : 可以把字符串变成具有固定长度的32位十六进制字符串 """ # 撞库 """ 111222 => 00b7691d86d96aebd21dd9e138f90840 222333 => 00b7691d86d96aebd21dd9e138f90842 """ import hashlib import random # ### 基本语法 # (一)md5对象 # 1.创建md5对象 hs = hashlib.md5() # 2.把要加密的数据更新到对象中 [update => 把字节流更新到对象之后,进行加密] hs.update("111222".encode("utf-8")) # 3.获取十六进制的字符串 res = hs.hexdigest() print(res , len(res)) # 00b7691d86d96aebd21dd9e138f90840 # 加盐 (加key , 加一个关键字) hs = hashlib.md5("XBOYww_".encode()) hs.update("111222".encode()) res = hs.hexdigest() print(res) # 623e0e8d4ecabd638c36a5e40189ba8f # 动态加盐 res = str(random.randrange(100000,1000000)) hs = hashlib.md5(res.encode()) hs.update("111222".encode()) res = hs.hexdigest() print(res) # (二)sha系列算法 """无论是加盐 还是 加密密码,都需要数据类型为二进制字节流""" # hs = hashlib.sha1() # 结果是具有固定长度40位的十六进制字符串; hs = hashlib.sha512("XGIRLww_".encode()) # 结果是具有固定长度128位的十六进制字符串 hs.update("sha系列算法".encode()) res = hs.hexdigest() """20c2502d0e00bf8fe35ebfbf097049d1f070e7968f30ef3353ff33d311af50da6b3883bfb9ab411f9dc4cdcd2310b39f5815c6dc1c48cd138d07443a6bcdcd11 128""" print(res , len(res)) # (三)hmac加密算法 import hmac import os key = b"xdogaa_" msg = b"112233" # new(盐(字节流),密码(字节流) ) hm = hmac.new(key,msg) res = hm.hexdigest() """ eebe14b1c144092121236cb1e3da396a """ print(res , len(res)) # 动态加盐 """ os.urandom(位数) 返回随机的二进制字节流 res = os.urandom(10) print(res , len(res)) """ key = os.urandom(64) msg = b"112233" hm = hmac.new(key,msg) res = hm.hexdigest() print(res , len(res))View Code
""" 机器和机器之间的数据直接对接 """ import socket import hmac sk = socket.socket() sk.connect( ("127.0.0.1" , 9000) ) def auth(secret_key): # 接受服务端发送过来的随机二进制字节流 msg = sk.recv(32) # hmac.new( key(字节流) , 要加密的内容(字节流) ) hm = hmac.new( secret_key.encode() , msg ) # 返回的是具有固定32位长度的十六进制字符串 cli_res = hm.hexdigest() # 把最后计算的结果发送给服务端进行校验 sk.send( cli_res.encode() ) # 接受服务端给予的校验结果 res = sk.recv(1024).decode() return res # 处理收发数据的逻辑 secret_key = "不开,老妈没回来" secret_key = "小兔儿乖乖,把门开开" # 调用授权函数 res = auth(secret_key) if res == "True": print("服务器校验通过") else: print("服务器校验失败") sk.close()View Code
""" 机器和机器之间的数据直接对接 """ import socketserver import hmac import os class MyServer(socketserver.BaseRequestHandler): secret_key = "小兔儿乖乖,把门开开" def auth(self): conn = self.request # 创建一个随机的32位字节流 msg = os.urandom(32) # 把字节流发送给客户端 conn.send(msg) # 服务端进行数据校验 hm = hmac.new( self.secret_key.encode() , msg ) ser_res = hm.hexdigest() # 服务端接受客户端发送过来的数据结果 cli_res = conn.recv(1024).decode() # 进行比对,如果ok 返回True , 反之亦然 return True if ser_res == cli_res else False def handle(self): if self.auth(): self.request.send("True".encode()) else: self.request.send("False".encode()) server = socketserver.ThreadingTCPServer( ("127.0.0.1" , 9000) , MyServer ) # 开启,让一个端口绑定多个程序; 模块.类.属性 = True socketserver.TCPServer.allow_reuse_address = True server.serve_forever()View Code
import socket import json """ pickle => 字节流( 存储数据 ) json => 字符串( 数据交互 ) """ sk = socket.socket() sk.connect( ("127.0.0.1" , 9001) ) # 处理收发数据的逻辑 usr = input("请输入您的用户名:") pwd = input("请输入您的密码:") dic = {"username" : usr , "password":pwd , "operate" : "login"} # 通过json变成字符串 res = json.dumps(dic) # 转化成字节流发送给服务端 sk.send(res.encode()) # 接受服务端响应的数据 res_str = sk.recv(1024).decode() # 字符串转化成字典 dic = json.loads(res_str) print(dic , type(dic)) print(dic["msg"]) sk.close()View Code
from collections import Iterator,Iterable import socketserver import hashlib import json class MyServer(socketserver.BaseRequestHandler): # 默认没有登录 sign = False def get_md5_code(self,usr,pwd): hs = hashlib.md5(usr.encode()) hs.update(pwd.encode()) return hs.hexdigest() def auth(self): conn = self.request # 接受客户端发送过来的数据,通过decode反解成字符串 res = conn.recv(1024).decode() # 通过json把字符串 转换成 字典 dic = json.loads(res) # {'username': 'caijingguan', 'password': '8888', 'operate': 'login'} print(dic , type(dic)) with open("userinfo.data",mode="r",encoding="utf-8") as fp: # fp文件对象是迭代器,一行一行返回数据 for i in fp: # 文件中解析出用户和密码 usr,pwd = i.strip().split(":") if usr == dic["username"] and pwd == self.get_md5_code( dic["username"] , dic["password"] ) : # 自定义返回的字典数据 dic_msg = {"code":1,"msg":"登录成功"} # 把字典 => 字符串 json_str = json.dumps(dic_msg) # 把字符串 => 字节流 发送给客户端 conn.send( json_str.encode() ) # 把sign标记从False => True 代表登录成功 self.sign = True break # 没有找到对应合法的用户名和密码,登录失败 if self.sign == False: dic_msg = {"code":0,"msg":"登录失败"} res = json.dumps(dic_msg).encode() conn.send(res) def handle(self): self.auth() server = socketserver.ThreadingTCPServer( ("127.0.0.1" , 9001) , MyServer ) # 开启,让一个端口绑定多个程序; 模块.类.属性 = True socketserver.TCPServer.allow_reuse_address = True server.serve_forever()View Code
创建一个userinfo.data文件存储用户数据 密码用hshlib加密
userinfo.data
wangwen:bbccc59bedc09e551a394699b44ed9f9 lisi:c79439cf9abcbd6c6d46e45766a9e64aView Code