diff --git a/lib/nwman.py b/lib/nwman.py new file mode 100644 index 0000000..3f9aa56 --- /dev/null +++ b/lib/nwman.py @@ -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 \ No newline at end of file diff --git a/tycrypto.py b/lib/tycrypto.py similarity index 93% rename from tycrypto.py rename to lib/tycrypto.py index a1325e5..45af2ec 100644 --- a/tycrypto.py +++ b/lib/tycrypto.py @@ -4,20 +4,22 @@ from cryptography.hazmat.primitives.asymmetric import ed25519, x25519 from cryptography.hazmat.primitives.ciphers.aead import AESGCM class TyCryptoEngine: - def __init__(self, static_private_bytes=None): - if static_private_bytes: - self.id_priv = ed25519.Ed25519PrivateKey.from_private_bytes(static_private_bytes) + def __init__(self, wallet_bytes=None): + if wallet_bytes: + self.id_priv = ed25519.Ed25519PrivateKey.from_private_bytes(wallet_bytes) else: self.id_priv = ed25519.Ed25519PrivateKey.generate() self.id_pub = self.id_priv.public_key() 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.ek_priv = None self.aesgcm = None - def get_private_bytes(self) -> bytes: + def export_wallet(self) -> bytes: return self.id_priv.private_bytes_raw() def make_handshake_packet(self, receiver_id: int) -> bytes: @@ -80,7 +82,6 @@ class TyCryptoEngine: @staticmethod def parse_header(header_bytes: bytes) -> tuple[int, int, int]: - version = header_bytes[0] packet_type = header_bytes[1] sender_id = int.from_bytes(header_bytes[2:5], 'big') receiver_id = int.from_bytes(header_bytes[5:8], 'big')