Добавлен класс TyNetworkManager для управления сетевыми соединениями и класс TyCryptoEngine для шифрования сообщений
This commit is contained in:
parent
f57e525194
commit
4cdedfef83
78
lib/nwman.py
Normal file
78
lib/nwman.py
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
import socket
|
||||||
|
import threading
|
||||||
|
import sys
|
||||||
|
|
||||||
|
class TyNetworkManager:
|
||||||
|
def __init__(self, on_packet_received):
|
||||||
|
self.sock = None
|
||||||
|
self.on_packet_received = on_packet_received
|
||||||
|
self.is_running = False
|
||||||
|
|
||||||
|
def connect(self, host: str, port: int) -> bool:
|
||||||
|
try:
|
||||||
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.sock.connect((host, port))
|
||||||
|
self.is_running = True
|
||||||
|
threading.Thread(target=self._read_loop, daemon=True).start()
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_packet(self, packet: bytes) -> bool:
|
||||||
|
if not self.sock or not self.is_running:
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
self.sock.sendall(packet)
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
self.disconnect()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def register_id(self, my_id: int):
|
||||||
|
header = bytes([0x01, 0x03]) + my_id.to_bytes(3, 'big') + (0).to_bytes(3, 'big')
|
||||||
|
meta = b'\x00' * 12 + (0).to_bytes(4, 'big')
|
||||||
|
self.send_packet(header + meta)
|
||||||
|
|
||||||
|
def disconnect(self):
|
||||||
|
self.is_running = False
|
||||||
|
if self.sock:
|
||||||
|
try:
|
||||||
|
self.sock.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
self.sock = None
|
||||||
|
|
||||||
|
def _read_loop(self):
|
||||||
|
while self.is_running:
|
||||||
|
try:
|
||||||
|
header = self._recv_exact(8)
|
||||||
|
if not header:
|
||||||
|
break
|
||||||
|
|
||||||
|
meta = self._recv_exact(16)
|
||||||
|
if not meta:
|
||||||
|
break
|
||||||
|
|
||||||
|
iv = meta[0:12]
|
||||||
|
payload_len = int.from_bytes(meta[12:16], 'big')
|
||||||
|
|
||||||
|
payload = b""
|
||||||
|
if payload_len > 0:
|
||||||
|
payload = self._recv_exact(payload_len)
|
||||||
|
if not payload:
|
||||||
|
break
|
||||||
|
|
||||||
|
self.on_packet_received(header, iv, payload)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
break
|
||||||
|
self.disconnect()
|
||||||
|
|
||||||
|
def _recv_exact(self, length: int) -> bytes:
|
||||||
|
data = b""
|
||||||
|
while len(data) < length:
|
||||||
|
chunk = self.sock.recv(length - len(data))
|
||||||
|
if not chunk:
|
||||||
|
return b""
|
||||||
|
data += chunk
|
||||||
|
return data
|
||||||
|
|
@ -4,20 +4,22 @@ from cryptography.hazmat.primitives.asymmetric import ed25519, x25519
|
||||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||||
|
|
||||||
class TyCryptoEngine:
|
class TyCryptoEngine:
|
||||||
def __init__(self, static_private_bytes=None):
|
def __init__(self, wallet_bytes=None):
|
||||||
if static_private_bytes:
|
if wallet_bytes:
|
||||||
self.id_priv = ed25519.Ed25519PrivateKey.from_private_bytes(static_private_bytes)
|
self.id_priv = ed25519.Ed25519PrivateKey.from_private_bytes(wallet_bytes)
|
||||||
else:
|
else:
|
||||||
self.id_priv = ed25519.Ed25519PrivateKey.generate()
|
self.id_priv = ed25519.Ed25519PrivateKey.generate()
|
||||||
|
|
||||||
self.id_pub = self.id_priv.public_key()
|
self.id_pub = self.id_priv.public_key()
|
||||||
self.id_pub_bytes = self.id_pub.public_bytes_raw()
|
self.id_pub_bytes = self.id_pub.public_bytes_raw()
|
||||||
|
|
||||||
|
# Наш неизменный ID (6 знаков), намертво привязанный к ключу
|
||||||
self.my_id = int(hashlib.sha256(self.id_pub_bytes).hexdigest(), 16) % 1000000
|
self.my_id = int(hashlib.sha256(self.id_pub_bytes).hexdigest(), 16) % 1000000
|
||||||
|
|
||||||
self.ek_priv = None
|
self.ek_priv = None
|
||||||
self.aesgcm = None
|
self.aesgcm = None
|
||||||
|
|
||||||
def get_private_bytes(self) -> bytes:
|
def export_wallet(self) -> bytes:
|
||||||
return self.id_priv.private_bytes_raw()
|
return self.id_priv.private_bytes_raw()
|
||||||
|
|
||||||
def make_handshake_packet(self, receiver_id: int) -> bytes:
|
def make_handshake_packet(self, receiver_id: int) -> bytes:
|
||||||
|
|
@ -80,7 +82,6 @@ class TyCryptoEngine:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_header(header_bytes: bytes) -> tuple[int, int, int]:
|
def parse_header(header_bytes: bytes) -> tuple[int, int, int]:
|
||||||
version = header_bytes[0]
|
|
||||||
packet_type = header_bytes[1]
|
packet_type = header_bytes[1]
|
||||||
sender_id = int.from_bytes(header_bytes[2:5], 'big')
|
sender_id = int.from_bytes(header_bytes[2:5], 'big')
|
||||||
receiver_id = int.from_bytes(header_bytes[5:8], 'big')
|
receiver_id = int.from_bytes(header_bytes[5:8], 'big')
|
||||||
Loading…
Reference in a new issue