websocket: 流程
ws 请求
sec-WebSocket-key: 前端传过来的,会变
magic_string: #固定值
加密后返回,建立连接 (服务端加密)
客户端发送的消息,服务端解密后查看
服务端发送加密的信息
解密:
与位运算 最大127
前端传过来(数据长度,解密所需字符串,数据)
加密:后台加密后传过去数据
import socket, base64, hashlib import websocket_jiemi import websocket_jiami sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('127.0.0.1', 9527)) sock.listen(5) # 获取客户端socket对象 conn, address = sock.accept() # 阻塞 # 获取客户端的【握手】信息 data = conn.recv(2048) print(data) """ b' GET / HTTP/1.1 Host: 127.0.0.1:9527 Connection: Upgrade Pragma: no-cache Cache-Control: no-cache User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36 Upgrade: websocket Origin: http://localhost:63342 Sec-WebSocket-Version: 13 Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Sec-WebSocket-Key: tPWfDfGthkhhqfY4ZdT1yQ== Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits ' """ # # # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11 #固定值 magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' # # def get_headers(data): header_dict = {} header_str = data.decode("utf8") for i in header_str.split(" "): if str(i).startswith("Sec-WebSocket-Key"): header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip() return header_dict headers = get_headers(data) # 提取请求头信息 Sec-WebSocket-Key # # 对请求头中的sec-websocket-key进行加密 # value = headers['Sec-WebSocket-Key'] + magic_string # jtl/vockZ8GRyadFVeiUTA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11 print(value) sha1_value = hashlib.sha1(value.encode('utf-8')).digest() #字节 print("sha1_value",sha1_value) ac = base64.b64encode(sha1_value) #字节 print("ac",ac) # ac = base64(sha1(sec+magic)) response_tpl = "HTTP/1.1 101 Switching Protocols " "Upgrade:websocket " "Connection: Upgrade " "Sec-WebSocket-Accept: %s " "WebSocket-Location: ws://127.0.0.1:9527 " response_str = response_tpl % (ac.decode('utf-8')) # 响应【握手加密后的】信息 conn.send(response_str.encode("utf8")) while True: msg = conn.recv(8096) msg = websocket_jiemi.websocket_jiema(msg) # conn.send("123123123123".encode("utf8")) send_str = websocket_jiami.jiami("hello".encode("utf8")) print(send_str) conn.send(send_str)
# b'x81x83xceHxb6x85xffzx85' hashstr = b'x81x85$xcb>x14LxaeRxK' # b'x81 # x85$ # xcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14L # xaeRxKxcb>x14LxaeRxK # xcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxK' # 将第二个字节也就是 x83 第9-16位 进行与127进行位运算 def websocket_jiema(hashstr): print(hashstr[1]) payload = hashstr[1] & 127 print(payload) #位运算后的结果 if payload == 127: extend_payload_len = hashstr[2:10] # 834473503 数据长度 mask = hashstr[10:14] #解密所需字符串 decoded = hashstr[14:] #数据 # 当位运算结果等于127时,则第3-10个字节为数据长度 # 第11-14字节为mask 解密所需字符串 # 则数据为第15字节至结尾 # # b'x81 # x85$ 126 # xcb>x14L 120 # xaeRxKxcb>x14LxaeRxK # xcb>x14LxaeRxKxcb>x14LxaeRxK xcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxKxcb>x14LxaeRxK' if payload == 126: extend_payload_len = hashstr[2:4] mask = hashstr[4:8] decoded = hashstr[8:] # 当位运算结果等于126时,则第3-4个字节为数据长度 # 第5-8字节为mask 解密所需字符串 # 则数据为第9字节至结尾 # # b'x81 # x85$ 5 len数据长度 # xcb>x14LxaeRxK' if payload <= 125: extend_payload_len = payload mask = hashstr[2:6] decoded = hashstr[6:] # 5 # 当位运算结果小于等于125时,则这个数字就是数据的长度 # 第3-6字节为mask 解密所需字符串 # 则数据为第7字节至结尾 # str_byte = bytearray() #字节的列表,里面存放传过来的字节,自动拼成字节串 # for i in range(len(decoded)): byte = decoded[i] ^ mask[i % 4] #或运算 str_byte.append(byte) # return str_byte.decode("utf8") #解密运算完后的前端穿过来的信息
import struct #加密使用 # msg_bytes = "哎呀妈呀脑瓜疼".encode("utf8") def jiami(msg_bytes): token = b"x81" length = len(msg_bytes) #发送到客服端的真实数据的字节长度 # 该模块可以把一个类型,如数字,转成固定长度的bytes # struct.pack('i',1111111111111) if length < 126: token += struct.pack("B", length) # x85$ elif length == 126: token += struct.pack("!BH", 126, length) else: token += struct.pack("!BQ", 127, length) msg = token + msg_bytes return msg #加密后的字节信息
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> <script> var ws = new WebSocket("ws://127.0.0.1:9527") ws.onmessage = function (data) { console.log(data.data) } </script> </html>