hashlib(hmac)进阶之client跟server交互
首先我还是要强调不管任何相同的字符串通过hashlib加密之后都会产生相同的32位字符串,这个是日常Web中常用的加密算法如果我的client发送一个请求过来我server接受到后就要对该密码进行判断,正常的流程是我需要把client端发送过来的请求转换成hashlib格式的字符串跟我存在数据库中的字符串进行对比做判断,当前我也可以在这些字符串加密前加盐(key)
以下是我的基础的server代码
代码解析:
首先我们需要明白Tcp下的服务端的7步曲
1.实例化socket对象
sk = socket.socket()
2绑定对应的服务器IP地址以及对外开放的端口
sk.bind(("127.0.0.1",8888))
3启动监听等待用户访问
sk.listen()
4建立tcp下的基本连接协议
conn,addr = sk.accept()
#5通讯的逻辑
rse = conn.recv(1024)#指定接收1024的字符串
conn.send("相信你自己就是最牛逼的哪一个".decode("utf-8"))
#6四次挥手断开连接
conn.close()
#7退还端口
sk.close()
这就是基础的服务端的代码
下面我要对服务端进行改造改造代码如下
# ### 服务器
import socket
import hmac
import os def auth(conn,secret_key):
# 随机的32位二进制字节流
res = os.urandom(32)
# 把res发送给对方的服务器
conn.send(res)
# 用hmac加密字符串
hm = hmac.new(secret_key.encode(),res)
# 通过hexdigest返回32长度的十六进制字符串
res_server = hm.hexdigest()
print(res_server) # 接受客户端发过来的加密后的字符串
res_cli = conn.recv(1024).decode("utf-8") if res_server == res_cli:
print("该用户是合法的链接请求")
return True
else:
print("该用户是非法的链接请求")
return False # 创建对象
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sk.bind( ("127.0.0.1",9001) )
sk.listen()
conn,addr = sk.accept() # 收发数据的逻辑
secret_key = "ig不牛逼"
# 调用函数,验证权限
res = auth(conn,secret_key)
# 如果验证的结果是真的,就处理用户发送过来的请求,假的直接断开链接
if res:
print(conn.recv(1024).decode("utf-8")) conn.close()
sk.close()
注os.urondom()是os模块下的一种方法,随机产生指定位数的随机2进制字节流
此时我对收发逻辑做了一定的处理下面我为为我写的auth代码进行解析
自定义一个auth权限函数,该函数需要2个变量conn(客户端返回服务端的端口对象或链接对象),secret_key(盐也就是我要key )
1 在auth里面我随机生成了一个指定32位随机2进制字节流os.urandom(32)
2 我需要把我服务端生成的32位随机季节流发送给服务端 conn.send(res)
3 用hmac加密hmac.new(secret_key.encode(),res) 俩个参数(一个是我需要加入的盐,另外一个是我生成的32位随机2进制流)
通过hmac的加密我会产生一个新的数据流 而这个数据流与客户端发送过来的数据流是一致的话那么我就可以认为此时的数据所对应的结果是一致的密码匹配成功
4 接受客户端加密后的密码串进行反解
5 验证客户端的加密是否与服务端的加密内容是否一致
6返回判断的内容
如果auth判断的结果是Ture那么我就直接给客户端返回这个登录状态登录成功
否则则给客户端返回一个登录失败的状态
关闭连接
退还端口
客户端的代码
是首先需要对socket进行引入
import socket
sk = socket.socket()#实例化socket对象
sk .connect(("127.0.0.1",8888))#指定相对应的服务器访问
sk.send("相信你自己是最牛逼的哪一个".encode())#对服务器发送请求
res = sk.recv(1024).decode("utf-8")接受服务端给我返回的消息
sk.close()#退还端口
下面我队我客户端的代码进行优化
# ### 客户端
import socket
import hmac def auth(sk,secret_key):
# 收发数据的逻辑
msg = sk.recv(32)
# 把key 和 msg 扔到new当中,进行加密
hm = hmac.new(secret_key.encode(),msg)
# 通过hexdigest把加密后的结果返回出来
res_cli = hm.hexdigest()
print(res_cli)
# 把加密好的字符串在发送回原服务器
sk.send(res_cli.encode()) sk = socket.socket()
sk.connect( ("127.0.0.1",9001) ) secret_key = "ig不牛逼"
# 调用函数,验证权限
auth(sk,secret_key)
# 向服务器发出下载的请求
sk.send(b"download") # 关闭链接
sk.close()
首先基于原始的client与服务端的通信下我对我的收发数据的逻辑进行了改造
自定义一个auth权限函数,该函数需要2个变量sk(客户端要与服务端的端口对象或链接对象),secret_key(盐也就是我要key )
1 我需要把我客户端接受服务端给我发送的32位随机2进制流 sk.recv(32)
3 用hmac加密hmac.new(secret_key.encode(),res) 俩个参数(一个是我需要加入的盐,另外一个是我生成的32位随机2进制流)
通过hmac的加密我会产生一个新的数据流 而这个数据流我会发送给服务端数,如果我客户端收缩加密的字节流与服务端加密的是一致的话我会得到服务端的校验判定
sk.close()#退还端口
传统简易的server与client登录验证交互
server代码
基于上面的代码我现在扩展模拟到数据库中取出我的账号以及密码并且对服务端发送过来的账户密码进行验证,如果验证成功我就给客户端返回登录状态
以下是代码
# ### 服务端
import hashlib
import socket
import json def get_md5_code(usr,pwd):
# 将用户名作为加密的盐key
hm = hashlib.md5(usr.encode())
hm.update(pwd.encode())
res = hm.hexdigest()
return res sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sk.bind( ("127.0.0.1",9000) )
sk.listen()
conn,addr = sk.accept() # 处理收发数据的逻辑
# 先接受二进制字节流 -> 字符串
msg = conn.recv(1024).decode()
print(msg,type(msg))
# 把字符串 -> 字典
dic = json.loads(msg)
print(dic,type(dic)) # 标识符,默认False
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"]):
# 登陆成功 返回状态吗为1
res = {"code":1}
res_msg = json.dumps(res).encode()
conn.send(res_msg)
# 如果登录成功,默认改成True
sign = True
break if sign == False:
#登录失败,返回状态码为0
res = {"code":0}
conn.send(json.dumps(res).encode()) # 四次挥手
conn.close()
# 退还端口
sk.close()
代码解析
def get_md5_code(usr,pwd):
# 将用户名作为加密的盐key
hm = hashlib.md5(usr.encode())
hm.update(pwd.encode())
res = hm.hexdigest()
return res
这里代码的主要作用是把用户名作为盐(key),pwd作为要加密的字符串
返回的是一个加盐(key)后的随机32位字符串,当我收到客户端的数据后需要经过json 字符串的反解后得到的一个字典,该字典包含了密码以及用户名的一种数据
此时我需要把字典的用户名以及密码拿出来做加密后跟数据库所存的随机字符串做比对,如果比对成功那么我就会给客户端返回一个状态反之给客户端返回一个否定的状态
下面我要介绍我的客户端的代码
# ### 客户端
import socket
import json
sk = socket.socket()
sk.connect( ("127.0.0.1",9000) ) usr = input("请输入您的账户:")
pwd = input("请输入您的密码:")
dic = {"username":usr,"password":pwd,"operate":"login"}
# 返回json格式的字符串
res = json.dumps(dic)
# 在把json字符串转换成字节流
bytes_msg = res.encode()
# 发送给服务端
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()
首先在客户端中我要生成一个字典,字典里面包含了我的账户以及密码名我通过json下的dumps强制把字典转换为json类型的字符串,通过这个字符串我直接发给服务端,让服务端帮我操作,如果匹配成功那么我就返回一个已经登录的状态,反之登录失败
hashlib(hmac)进阶之client跟server交互的更多相关文章
- 深入浅出 Redis client/server交互流程
综述 最近笔者阅读并研究redis源码,在redis客户端与服务器端交互这个内容点上,需要参考网上一些文章,但是遗憾的是发现大部分文章都断断续续的非系统性的,不能给读者此交互流程的整体把握.所以这里我 ...
- Python——常用模块(time/datetime, random, os, shutil, json/pickcle, collections, hashlib/hmac, contextlib)
1.time/datetime 这两个模块是与时间相关的模块,Python中通常用三种方式表示时间: #时间戳(timestamp):表示的是从1970年1月1日00:00:00开始按秒计算的偏移量. ...
- [从源码学设计]蚂蚁金服SOFARegistry 之 如何与Meta Server交互
[从源码学设计]蚂蚁金服SOFARegistry 之 如何与Meta Server交互 目录 [从源码学设计]蚂蚁金服SOFARegistry 之 如何与Meta Server交互 0x00 摘要 0 ...
- UDP编程中client和server中使用recvfrom和sendto的区别
client中: sendto(sfd,buf,strlen(buf),0,(struct sockaddr *)&saddr,len); recvfrom(sfd,buf ...
- tmux protocol version mismatch (client 7, server 6)
$ tmux attach protocol version mismatch (client 7, server 6) $ pgrep tmux 3429 $ /proc/3429/exe atta ...
- New full duplex HTTP tunnel implementation (client and server)
https://issues.jboss.org/browse/NETTY-246?page=com.atlassian.jirafisheyeplugin:fisheye-issuepanel —— ...
- jvm的client和server
最近研究c++代码调用java的jar,发现64位的下的jvm在server路径,而32位的jvm则存在client路径下面,于是十分好奇,查了下,这里做个记录 JVM Server模式与client ...
- Android简单的聊天室开发(client与server沟通)
请尊重他人的劳动成果.转载请注明出处:Android开发之简单的聊天室(client与server进行通信) 1. 预备知识:Tcp/IP协议与Socket TCP/IP 是Transmission ...
- 【Python】 hash值计算 hashlib & hmac
hashlib & hmac *不是很清楚能不能把这种hash值取样算法称之为加密,但是似乎好像也是这么说的哈(非科班出身的野路子就是没这种基本知识的) ■ 基本用法 hashlib支持MD5 ...
随机推荐
- 9-SQL视图
(1) 如何创建,更新和删除视图 视图作为一张虚拟表,帮我们封装了底层与数据表的接口.它相当于是一张表或多张表的数据结果集.视图的这一特点,可以帮我们简化复杂的 SQL 查询,比如在编 ...
- Master Note: Troubleshooting ORA-1548 error (Doc ID 1577988.1)
APPLIES TO: Oracle Database Cloud Schema Service - Version N/A and laterOracle Database Exadata Clou ...
- Ubuntu18.04安装Cuda10.1
注:如果使用anaconda,貌似不需要手动安装Cuda和cudnn,安装tensorflow时会自动安装 1.官方教程https://docs.nvidia.com/cuda/cuda-instal ...
- .net core从版本 3.0 迁移到 3.1引发的BUG
前几天微软的.net core3.1发布后,随把visual studio 2019升级到16.4.1版本并把项目进行框架升级.升级后的项目在IdentityServer4授权后在360安全浏览器竟然 ...
- 渗透测试学习 十、 MSsql注入下
大纲:MySQL介绍及操作 MySQL注入原理 MySQL注入其他操作 一.MySQL介绍及操作 介绍 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle ...
- 初学JavaScript正则表达式(四)
字符类 [] 一般情况下正则表达式中一个字符对应字符串一个字符 可以使用元字符 [ ] 来构建一个简单的类 类泛指符合某些特征的对象 例: 'a1b1c1d1'.replace(/[ab ...
- coco数据集标注图转为二值图python(附代码)
coco数据集大概有8w张以上的图片,而且每幅图都有精确的边缘mask标注. 后面后分享一个labelme标注的json或xml格式转二值图的源码(以备以后使用) 而我现在在研究显著性目标检测,需要的 ...
- shell的几个实战脚本例子(欠)
如何让shell实现 可选择性执行 的功能 巡检内存使用率 批量创建用户 场景:公司想要做测试,需要10000个用户 数据库里查询学生成绩 #如何登录mysql数据库 #如何写sql对数据进行操作 # ...
- 浅谈C++ STL deque 容器
浅谈C++ STL deque 容器 本篇随笔简单介绍一下\(C++STL\)中\(deque\)容器的使用方法及常见使用技巧. deque容器的概念 \(deque\)的意义是:双端队列.队列是我们 ...
- rss订阅
其实,本质上和爬虫没区别,只不过这是人家主动给你数据,而且是编排好格式后的数据 按个人主页url更新内容 去重,按照redis去重的方式 按时间保存内容 mysql 保存为时间格式(可以根据时间比较大 ...