websocket的加密和解密
补充个小知识点:按位与运算
按位与运算是同位都为1才为1,有一个不为1就是0
websocket_hand
1 import socket, base64, hashlib 2 import websocket_jiemi 3 import websocket_jiami 4 5 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 6 sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 7 sock.bind(('127.0.0.1', 9527)) 8 sock.listen(5) 9 # 获取客户端socket对象 10 conn, address = sock.accept() # 阻塞 11 12 # 获取客户端的【握手】信息 13 data = conn.recv(2048) 14 print(data) 15 16 17 """ 18 b' 19 GET / HTTP/1.1\r\n 20 Host: 127.0.0.1:9527\r\n 21 Connection: Upgrade\r\n 22 Pragma: no-cache\r\n 23 Cache-Control: no-cache\r\n 24 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36\r\n 25 Upgrade: websocket\r\n 26 Origin: http://localhost:63342\r\n 27 Sec-WebSocket-Version: 13\r\n 28 Accept-Encoding: gzip, deflate, br\r\n 29 Accept-Language: zh-CN,zh;q=0.9\r\n 30 Sec-WebSocket-Key: tPWfDfGthkhhqfY4ZdT1yQ==\r\n 31 Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits\r\n\r\n' 32 """ 33 # 34 # # magic string为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11 35 magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' 36 # 37 # 38 def get_headers(data): 39 header_dict = {} 40 header_str = data.decode("utf8") 41 for i in header_str.split("\r\n"): 42 if str(i).startswith("Sec-WebSocket-Key"): 43 header_dict["Sec-WebSocket-Key"] = i.split(":")[1].strip() 44 45 return header_dict 46 47 headers = get_headers(data) # 提取请求头信息 48 49 # # 对请求头中的sec-websocket-key进行加密 50 51 # 52 value = headers['Sec-WebSocket-Key'] + magic_string # jtl/vockZ8GRyadFVeiUTA==258EAFA5-E914-47DA-95CA-C5AB0DC85B11 53 print(value) 54 sha1_value = hashlib.sha1(value.encode('utf-8')).digest() 55 print("sha1_value",sha1_value) 56 ac = base64.b64encode(sha1_value) 57 print("ac",ac) 58 # ac - sha1(sec+magic) - base64 59 response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \ 60 "Upgrade:websocket\r\n" \ 61 "Connection: Upgrade\r\n" \ 62 "Sec-WebSocket-Accept: %s\r\n" \ 63 "WebSocket-Location: ws://127.0.0.1:9527\r\n\r\n" 64 65 response_str = response_tpl % (ac.decode('utf-8')) 66 # 响应【握手】信息 67 conn.send(response_str.encode("utf8")) 68 69 while True: 70 msg = conn.recv(8096) 71 msg = websocket_jiemi.websocket_jiema(msg) 72 73 # conn.send("123123123123".encode("utf8")) 74 send_str = websocket_jiami.jiami("hello".encode("utf8")) 75 print(send_str) 76 conn.send(send_str)
websocket_jiami
1 import struct 2 # msg_bytes = "哎呀妈呀脑瓜疼".encode("utf8") 3 def jiami(msg_bytes): 4 token = b"\x81" 5 length = len(msg_bytes) 6 7 if length < 126: 8 token += struct.pack("B", length) # \x85$ 9 elif length == 126: 10 token += struct.pack("!BH", 126, length) 11 else: 12 token += struct.pack("!BQ", 127, length) 13 14 msg = token + msg_bytes 15 16 return msg
websocket_jiemi
1 # b'\x81\x83\xceH\xb6\x85\xffz\x85' 2 3 hashstr = b'\x81\x85$\xcb>\x14L\xaeRxK' 4 # b'\x81 5 # \x85$ 6 # \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L 7 # \xaeRxK\xcb>\x14L\xaeRxK 8 # \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK' 9 10 # 将第二个字节也就是 \x83 第9-16位 进行与127进行位运算 11 12 def websocket_jiema(hashstr): 13 print(hashstr[1]) 14 payload = hashstr[1] & 127 15 print(payload) 16 17 if payload == 127: 18 extend_payload_len = hashstr[2:10] # 834473503 19 mask = hashstr[10:14] 20 decoded = hashstr[14:] 21 # 当位运算结果等于127时,则第3-10个字节为数据长度 22 # 第11-14字节为mask 解密所需字符串 23 # 则数据为第15字节至结尾 24 # 25 26 # b'\x81 27 # \x85$ 126 28 # \xcb>\x14L 120 29 # \xaeRxK\xcb>\x14L\xaeRxK 30 # \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK \xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK\xcb>\x14L\xaeRxK' 31 32 33 if payload == 126: 34 extend_payload_len = hashstr[2:4] 35 mask = hashstr[4:8] 36 decoded = hashstr[8:] 37 # 当位运算结果等于126时,则第3-4个字节为数据长度 38 # 第5-8字节为mask 解密所需字符串 39 # 则数据为第9字节至结尾 40 # 41 # b'\x81 42 # \x85$ 5 len数据长度 43 # \xcb>\x14L\xaeRxK' 44 45 if payload <= 125: 46 extend_payload_len = payload 47 mask = hashstr[2:6] 48 decoded = hashstr[6:] # 5 49 50 # 当位运算结果小于等于125时,则这个数字就是数据的长度 51 # 第3-6字节为mask 解密所需字符串 52 # 则数据为第7字节至结尾 53 # 54 str_byte = bytearray() 55 # 56 for i in range(len(decoded)): 57 byte = decoded[i] ^ mask[i % 4] 58 str_byte.append(byte) 59 # 60 return str_byte.decode("utf8")
my_socket
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 </body> 10 <script> 11 var ws = new WebSocket("ws://127.0.0.1:9527") 12 ws.onmessage = function (data) { 13 console.log(data.data) 14 15 } 16 </script> 17 </html>
越是困难的事越要立即去做,这样收益才会最大!!!