Python 在一条消息中通过 UDP 发送字符串和字节
Python Sending String and Bytes over UDP in One Message
在这个程序中,我试图通过 UDP 广播向客户端发送密钥共享。我面临的问题是将字符串和字节编码为一条消息,产生了很多错误。
我想从服务器向客户端发送一个随机 ID 和一个密钥共享,其中包括索引(整数)和共享(16 字节字符串)。我在 id、index 和 share 之间添加了“:”,以便稍后能够在客户端对其进行管理(通过将消息拆分为多个部分)。
我试过将所有内容都转换成字符串,例如:
message = (str(id) + ":" + str(index) + ":").encode('utf-16') + str(share, 'utf-16')
。但这会导致客户端的密钥重建出现问题,其中密钥共享应该是一个字节字符串,看起来像 b"b'\xff\xfej\xb9\xdb\x8c&\x7f\x06\x87\x98Ig\xfc\x1eJ\xf6\xb5'"
.
然后我尝试将 id 和索引编码为 utf-16 并向客户端发送消息,然后对其进行解码,但这并不能让我重建密钥并且出现错误:ValueError: The encoded value must be an integer or a 16 byte string
.
当我在客户端解码时,数据是这样的:f91f7e52-865d-49bc-bb45-ad80255e9ef9:5:륪賛缦蜆䦘ﱧ䨞뗶
。但是有些share解码后没有分界符,无法拆分。
有没有办法让服务器在一条消息中发送以下所有数据(id、索引、共享),以便在客户端正确分离?
服务器的期望输出是(id = string,index = int,share = 16-byte string):
id = f91f7e52-865d-49bc-bb45-ad80255e9ef9
index = 5
share = b'\xff\xfej\xb9\xdb\x8c&\x7f\x06\x87\x98Ig\xfc\x1eJ\xf6\xb5'
Server.py
from socket import *
import socket
import time
import uuid
from Crypto.Random import get_random_bytes
from Crypto.Protocol.SecretSharing import Shamir
server = socket.socket(AF_INET, SOCK_DGRAM)
server.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
id = uuid.uuid4()
# generate 16-byte key
key = get_random_bytes(16)
# prepare k chunks of key
shares = Shamir.split(3, 5, key)
while True:
for index, share in shares:
message = (str(id) + ":" + str(index) + ":").encode('utf-16') + share
# send bytes
server.sendto(message, ('<broadcast>', 37020))
print("message sent!")
time.sleep(1)
Client.py
from socket import *
from Crypto.Protocol.SecretSharing import Shamir
audienceSocket = socket(AF_INET, SOCK_DGRAM)
audienceSocket.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
audienceSocket.bind(('', 37020))
receivedShares = {}
reconstruct = []
while True:
# get data from sender
data, address = audienceSocket.recvfrom(1024)
decoded = data.decode('utf-16')
print("Decoded:", decoded)
id, index = decoded.split(":", 1)
index, share = index.split(":", 1)
share = share.encode('utf-16')
print(id)
print(index)
print(share)
if id not in receivedShares:
receivedShares[id] = set()
receivedShares[id].add((index, share))
print(receivedShares)
for shares in receivedShares:
if len(shares) >= 3:
for share in shares:
reconstruct.append(share)
# reconstrcut the key
key = Shamir.combine(reconstruct)
print("The key is:", key)
UUID可以编码为16字节的值,整数例如为 4 个字节,并且 share
的长度为 16 个字节。因此,数据可以简单地连接而无需定界符并按其长度分隔,例如:
import uuid
from Crypto.Random import get_random_bytes
from Crypto.Protocol.SecretSharing import Shamir
id_sender = uuid.uuid4()
key = get_random_bytes(16)
shares = Shamir.split(3, 5, key)
for index_sender, share_sender in shares:
# Encode
message = id_sender.bytes + index_sender.to_bytes(4, byteorder='big') + share_sender
# Send message via socket
# Decode
id_receiver = uuid.UUID(bytes=message[:16])
index_receiver = int.from_bytes(message[16:20], byteorder='big')
share_receiver = message[20:]
print(id_sender == id_receiver, index_sender == index_receiver, share_sender == share_receiver) # True True True
在这个程序中,我试图通过 UDP 广播向客户端发送密钥共享。我面临的问题是将字符串和字节编码为一条消息,产生了很多错误。
我想从服务器向客户端发送一个随机 ID 和一个密钥共享,其中包括索引(整数)和共享(16 字节字符串)。我在 id、index 和 share 之间添加了“:”,以便稍后能够在客户端对其进行管理(通过将消息拆分为多个部分)。
我试过将所有内容都转换成字符串,例如:
message = (str(id) + ":" + str(index) + ":").encode('utf-16') + str(share, 'utf-16')
。但这会导致客户端的密钥重建出现问题,其中密钥共享应该是一个字节字符串,看起来像 b"b'\xff\xfej\xb9\xdb\x8c&\x7f\x06\x87\x98Ig\xfc\x1eJ\xf6\xb5'"
.
然后我尝试将 id 和索引编码为 utf-16 并向客户端发送消息,然后对其进行解码,但这并不能让我重建密钥并且出现错误:ValueError: The encoded value must be an integer or a 16 byte string
.
当我在客户端解码时,数据是这样的:f91f7e52-865d-49bc-bb45-ad80255e9ef9:5:륪賛缦蜆䦘ﱧ䨞뗶
。但是有些share解码后没有分界符,无法拆分。
有没有办法让服务器在一条消息中发送以下所有数据(id、索引、共享),以便在客户端正确分离?
服务器的期望输出是(id = string,index = int,share = 16-byte string):
id = f91f7e52-865d-49bc-bb45-ad80255e9ef9
index = 5
share = b'\xff\xfej\xb9\xdb\x8c&\x7f\x06\x87\x98Ig\xfc\x1eJ\xf6\xb5'
Server.py
from socket import *
import socket
import time
import uuid
from Crypto.Random import get_random_bytes
from Crypto.Protocol.SecretSharing import Shamir
server = socket.socket(AF_INET, SOCK_DGRAM)
server.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
server.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
id = uuid.uuid4()
# generate 16-byte key
key = get_random_bytes(16)
# prepare k chunks of key
shares = Shamir.split(3, 5, key)
while True:
for index, share in shares:
message = (str(id) + ":" + str(index) + ":").encode('utf-16') + share
# send bytes
server.sendto(message, ('<broadcast>', 37020))
print("message sent!")
time.sleep(1)
Client.py
from socket import *
from Crypto.Protocol.SecretSharing import Shamir
audienceSocket = socket(AF_INET, SOCK_DGRAM)
audienceSocket.setsockopt(SOL_SOCKET, SO_REUSEPORT, 1)
audienceSocket.bind(('', 37020))
receivedShares = {}
reconstruct = []
while True:
# get data from sender
data, address = audienceSocket.recvfrom(1024)
decoded = data.decode('utf-16')
print("Decoded:", decoded)
id, index = decoded.split(":", 1)
index, share = index.split(":", 1)
share = share.encode('utf-16')
print(id)
print(index)
print(share)
if id not in receivedShares:
receivedShares[id] = set()
receivedShares[id].add((index, share))
print(receivedShares)
for shares in receivedShares:
if len(shares) >= 3:
for share in shares:
reconstruct.append(share)
# reconstrcut the key
key = Shamir.combine(reconstruct)
print("The key is:", key)
UUID可以编码为16字节的值,整数例如为 4 个字节,并且 share
的长度为 16 个字节。因此,数据可以简单地连接而无需定界符并按其长度分隔,例如:
import uuid
from Crypto.Random import get_random_bytes
from Crypto.Protocol.SecretSharing import Shamir
id_sender = uuid.uuid4()
key = get_random_bytes(16)
shares = Shamir.split(3, 5, key)
for index_sender, share_sender in shares:
# Encode
message = id_sender.bytes + index_sender.to_bytes(4, byteorder='big') + share_sender
# Send message via socket
# Decode
id_receiver = uuid.UUID(bytes=message[:16])
index_receiver = int.from_bytes(message[16:20], byteorder='big')
share_receiver = message[20:]
print(id_sender == id_receiver, index_sender == index_receiver, share_sender == share_receiver) # True True True