#hashlib 这个模块是一堆加密算法的集合体,哈希算法的加密方式不止一种
https://www.cmd5.com/ md5解密
# 应用场景:在需要效验功能时使用
用户密码的 => 加密,解密
相关效验的 => 加密,解密
#哈希算法也叫摘要算法,相同的数据始终得到相同的输出,不同的数据得到不同的输出。
#(1)哈希将不可变的任意长度的数据,变成具有固定长度的唯一值
(2)字典的键值对映射关系是通过哈希计算的,哈希存储的数据是散列(无序)
##mad加密(相比而言hmac加密的算法不会被破解)
加密效率快 通过的加密精密 方法安全性稍差 位数是32位
# 基本用法 # (1)创建一个md5算法的对象 # (2)把想要加密的字符串通过update方法更新到hs这个对象当中去 # 参数是二进制字节流 # (3)返回的是32位16进制的字符串 # 加盐(加key 只有你自己知道的明文) 目的:增加密码的复杂度
# 加盐是在用md5后者是sha1()或者sha512()时候假如参数key
# 在hashlib.md5(key) # 动态加盐
hs = hashlib.md5() hs.update("wangwenshuaige".encode("utf-8")) res = hs.hexdigest() print(res,len(res)) # a9d3c3ad36ff18b5bc7be96295df079b 32 # 加盐(加key 只有你自己知道的明文) 目的:增加密码的复杂度 hs = hashlib.md5("Xboyww_".encode("utf-8")) hs.update("123".encode("utf-8")) res = hs.hexdigest() print(res) # 1ea36fffc2174b753b4c47d3deeaca60 # 动态加盐 import random res = str(random.randrange(10000,1000000)) hs = hashlib.md5(res.encode()) hs.update("aabbccdd".encode()) res = hs.hexdigest() print(res) # 485e1769395b018243d7ee16f2540219
## sha
加密效率慢,算法相对来说 安全性稍高
# 1.创建一个对象
# 2. 对象.update(key) 写入的数据都是字节流的
# 比如:hs = hashlib.sha1()
hs.update("xboyww_123".encode("utf-8"))
hs = hashlib.sha1() hs.update("xboyww_123".encode("utf-8")) res = hs.hexdigest() # 返回的加密字符串长度是40位 print(res,len(res)) # 4f584b41e8cca8c45f4875ddbfa8113dffa36e31 40 # 加盐 hs = hashlib.sha1("PPUU".encode("utf-8")) hs.update("xboyww_123".encode()) res = hs.hexdigest() print(res) # 744316f7f3c985b49c3b0412f5e8444ea861c4d1 # sha512 hs = hashlib.sha512() hs.update("12345".encode()) res = hs.hexdigest() # 返回的字符串长度是128位 print(res,len(res)) # 3627909a29c31381a071ec27f7c9ca97726182aed29a7ddd2e54353322cfb30abb9e3a6df2ac2c20fe23436311d678564d0c8d305930575f60e2d3d048184d79 128
import hmac import os key = b"124" msg = b"456" hm = hmac.new(key,msg) res = hm.hexdigest() print(res,len(res)) # abd3b78f7a6c0a170381a7094c09c777 32 # 随机返回长度为32位的二进制字节流 key = os.urandom(32) print(key) # b'\xfe\xf2\xe3\xf7\xb7\xcc@\x8dLx\xf42\x85\xbd\x99Z\xfa\xe0\x9f\x0c\xe0\xa2\x9bT\xb2h\xd8\x1b\xeb\x98J\x15' hm = hmac.new(key,msg) res = hm.hexdigest() print(res,len(res)) # 5c7e1d2e4d48bd14149a8afe5f4904fc 32
(1)针对小文件的内容校验 import hashlib def check_md5(file): with open(file,mode="rb") as fp: hs = hashlib.md5() hs.update(fp.read()) return hs.hexdigest() print(check_md5("ceshi1.txt")) print(check_md5("ceshi2.txt")) # 62c629da1d7f164bb85e2d741b77610e # b949a12fb038471495f0cdb8db640562
# 可以连续的对内容就行校验
hs = hashlib.md5() hs.update("昨天晚上\n下雨了".encode()) res = hs.hexdigest() print(res) # 894c4dd4b1f57472322db524e7b6a47f # 可以连续update到hs独享就行字节流的拼接 hs = hashlib.md5() hs.update("昨天晚上\n".encode()) hs.update("下雨了".encode()) res = hs.hexdigest() print(res) # 894c4dd4b1f57472322db524e7b6a47f
# 方法一 def check_md5(file): hs = hashlib.md5() with open(file,mode="rb") as fp: while True: content = fp.read(1) if content: hs.update(content) else: break return hs.hexdigest() print("<=======>") print(check_md5("ceshi1.txt")) print(check_md5("ceshi2.txt")) # 62c629da1d7f164bb85e2d741b77610e # b949a12fb038471495f0cdb8db640562
# 方法二
import os def check_md5(file): hs = hashlib.md5() file_size = os.path.getsize(file) with open(file,mode="rb") as fp: while file_size: # read(1) content = fp.read(1) hs.update(content) file_size -= len(content) return hs.hexdigest() print(check_md5("ceshi1.txt")) print(check_md5("ceshi2.txt")) # 62c629da1d7f164bb85e2d741b77610e # b949a12fb038471495f0cdb8db640562
# 利用创建出来的对象可以持续的update()即是你需要校验的内容,如果需要加(加盐)key(明文)就在创造对象的时候加入。
hs = hashlib.md5("Xboyww_".encode("utf-8"))
小结:方法1是利用一个死循环,每次在里面就行读取一个字节,如果读到有数据的话就就行update()把要校验的内容加进去。直到fp.read(1)读不到数据的时候就行退出,最后返回一个hs.hexdigest()
方法二是利用判断文件大小作为循环的条件,一样的就行每次读取一个字节,利用update()方法就行更新hs对象,直到文件对象file_size的长度为0的时候,说明要校验的内容已经全部写入hs对象中去了。
最后直接返回hs.hexdigest()
b"wangwendashuaige"
# 客户端代码
import socket import hmac def auth(sk,key): # 接受服务器发过来的随机二进制字节流 msg = sk.recv(32) # print(msg) hm = hmac.new(key,msg) res = hm.hexdigest() # 把加密后的字符串发送给服务器 sk.send(res.encode()) sk = socket.socket() key = b"wangwendashuaige" sk.connect( ("127.0.0.1",9000) ) auth(sk,key) sk.send(b"download") sk.close()
# 服务器代码
# server 服务端 添加访问的权限验证 import socket import hmac import os def auth(conn,secret_key): # 随机获取二进制的字节流 msg = os.urandom(32) # print(msg) conn.send(msg) hm = hmac.new(secret_key,msg) res_serve = hm.hexdigest() # 接受客户端发给我的字符串 res_client = conn.recv(1024).decode("utf-8") if res_serve == res_client: print("合法的链接") return True else: print("不合法的链接") return False sk = socket.socket() sk.bind( ("127.0.0.1",9000) ) sk.listen() conn,addr = sk.accept() secret_key = b"wangwendashuaige" if auth(conn,secret_key): # 如果返回真,可以接受客户发来的各种请求 print(conn.recv(1024).decode("utf-8")) # 收发数据逻辑. # ... # 四次挥手 conn.close() # 退还端口 sk.close()
运行代码:True
2.带有输入用户名和密码的,访问服务器(已经存好了可以访问的内容),程序过程是:
1.通过将输入的用户名还有密码通过json转换为字符串再
2.通过encode变成二进制字节流,然后使用hashlib就行加密发送
3.到了服务器端,就行decode()得到当初定义的字典,这个时候需要访问服务器端的数据库的数据就行文件的比对:
但是本例子中服务器去拿数据的时候,不是拿的数据库的数据而是自己创建的数据,直接通过打开文件数据就行获取就行,但是注意数据的格式,以及收到的数据不要搞混淆了。
服务器中的数据类型是通过hashlib加密过的(本例中的是:# zhangsan:e7a6d0f97db7ea1c4a0c1c137cbf771c;也就是密码是经过hashlib的)。接收到客户端的数据是字节流,
如果是正确的:返回一个字典{“code”:1} 并把标记状态的sign = True(最初定义的是False,定义这个状态方便我们就行在客户端就行接受一个数据,从而反应出访问的结果)
4.通过一变量的增加(sign=0,成功之后是sign=1,不做处理如果是sign=0后面继续写逻辑),并发送回客户端,让客户端知道反应结果。
服务器数据库中存放的数据是:
服务器代##服务器登录import socket
import json import hashlib def get_md5_code(usr,pwd): hs = hashlib.md5(usr.encode()) hs.update(pwd.encode()) return hs.hexdigest() sk = socket.socket() sk.bind(("127.0.0.1",9001)) sk.listen() conn,addr = sk.accept() #把接受到客户端的字节流变成字符串 msg = conn.recv(1024).decode() # 反序化字典 dic = json.loads(msg) # 默认编辑用户不存在 sign = False
# 提取服务器中的数据 with open("userinfo.txt",mode="r",encoding="utf-8") as fp: for line in fp:
usr,pwd = line.strip().split(":") if usr == dic['username'] and pwd == get_md5_code(dic['username'],dic['password']): res = {"code":1} res_msg = json.dumps(res).encode() conn.send(res_msg) # 该用户找到了,存在 sign = True break if sign == False: res = {"code":0} res_msg = json.dumps(res).encode() conn.send(res_msg) conn.close() sk.close()
客户端代码:
### 客户端 import socket import json ## 张三 111 # 李四 222 # 王五 333 # 赵六 444 sk = socket.socket() sk.connect(("127.0.0.1", 9001)) # 收发数据逻辑 usr = input("请输入用户名:") pwd = input("请输入您的密码:") dic = {"username": usr, "password": pwd, "operation":"login"} # 把字典序列化成字符串 json_dic = json.dumps(dic) # 把字符串变成字节流 bytes_msg = json_dic.encode("utf-8") sk.send(bytes_msg) # 接受服务器的返回值 res_msg = sk.recv(1024).decode() # 反序列化成字典 dic_code = json.loads(res_msg) if dic_code['code']: print("恭喜你,登录成功!") else: print("抱歉,登录失败!") sk.close