From 72c566b7ab373849f29a5fdc88ff52e8521d69e5 Mon Sep 17 00:00:00 2001 From: nikhil <72266969+Nikhil-karoriya@users.noreply.github.com> Date: Fri, 10 Oct 2025 11:13:18 +0530 Subject: [PATCH 1/2] Add P2P file sharing algorithm in Python --- peer2peer_file_sharing/crypto/aes_crypto.py | 37 ++++ peer2peer_file_sharing/crypto/rsa_crypto.py | 63 +++++++ peer2peer_file_sharing/peer.py | 191 ++++++++++++++++++++ peer2peer_file_sharing/utils/file_utils.py | 36 ++++ 4 files changed, 327 insertions(+) create mode 100644 peer2peer_file_sharing/crypto/aes_crypto.py create mode 100644 peer2peer_file_sharing/crypto/rsa_crypto.py create mode 100644 peer2peer_file_sharing/peer.py create mode 100644 peer2peer_file_sharing/utils/file_utils.py diff --git a/peer2peer_file_sharing/crypto/aes_crypto.py b/peer2peer_file_sharing/crypto/aes_crypto.py new file mode 100644 index 000000000000..130b0124e837 --- /dev/null +++ b/peer2peer_file_sharing/crypto/aes_crypto.py @@ -0,0 +1,37 @@ +import zlib +from cryptography.fernet import Fernet + +SKIP_COMPRESSION_EXTENSIONS = { + '.zip', '.gz', '.bz2', '.xz', '.rar', '.7z', + '.jpg', '.jpeg', '.png', '.gif', '.webp', + '.mp3', '.mp4', '.avi', '.mkv', '.mov', + '.pdf' +} + +def generate_aes_key(): + return Fernet.generate_key() + +def encrypt_chunk_with_aes(chunk: bytes, aes_key: bytes, file_extension: str) -> bytes: + fernet = Fernet(aes_key) + if file_extension.lower() not in SKIP_COMPRESSION_EXTENSIONS: + try: + chunk = zlib.compress(chunk) + except Exception as e: + print(f"\n[!] Compression failed: {e}") + + return fernet.encrypt(chunk) + +def decrypt_chunk_with_aes(chunk: bytes, aes_key: bytes, file_extension: str) -> bytes: + fernet = Fernet(aes_key) + try: + decrypted_data = fernet.decrypt(chunk) + except Exception as e: + raise Exception(f"\n[!] AES decryption failed: {e}") + + if file_extension.lower() not in SKIP_COMPRESSION_EXTENSIONS: + try: + decrypted_data = zlib.decompress(decrypted_data) + except zlib.error: + print("\n[!] Warning: Failed to decompress — file may not be compressed") + + return decrypted_data \ No newline at end of file diff --git a/peer2peer_file_sharing/crypto/rsa_crypto.py b/peer2peer_file_sharing/crypto/rsa_crypto.py new file mode 100644 index 000000000000..98f599001070 --- /dev/null +++ b/peer2peer_file_sharing/crypto/rsa_crypto.py @@ -0,0 +1,63 @@ +from cryptography.hazmat.primitives import serialization, hashes +from cryptography.hazmat.primitives.asymmetric import rsa, padding + +def generate_rsa_key_pair(private_path: str, public_path: str): + private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) + + with open(private_path, "wb") as f: + + f.write(private_key.private_bytes( + serialization.Encoding.PEM, + serialization.PrivateFormat.TraditionalOpenSSL, + serialization.NoEncryption() + )) + + with open(public_path, "wb") as f: + + f.write(private_key.public_key().public_bytes( + serialization.Encoding.PEM, + serialization.PublicFormat.SubjectPublicKeyInfo + )) + +def encrypt_with_rsa_public_key(data: bytes, public_key_path: str) -> bytes: + + with open(public_key_path, "rb") as f: + public_key = serialization.load_pem_public_key(f.read()) + + if not isinstance(public_key, rsa.RSAPublicKey): + raise TypeError("\n[!] The loaded public key is not an RSA key.") + + return public_key.encrypt( + data, + padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None) + ) + +def decrypt_with_rsa_private_key(ciphertext: bytes, private_key_path: str) -> bytes: + + with open(private_key_path, "rb") as f: + private_key = serialization.load_pem_private_key(f.read(), password=None) + + if not isinstance(private_key, rsa.RSAPrivateKey): + raise TypeError("\n[!] The loaded private key is not an RSA key.") + + return private_key.decrypt( + ciphertext, + padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None) + ) + +def is_valid_pem_key(file_path: str, is_private: bool = False) -> bool: + + try: + with open(file_path, "rb") as f: + data = f.read() + if not data: + return False + if is_private: + serialization.load_pem_private_key(data, password=None) + else: + serialization.load_pem_public_key(data) + return True + + except Exception: + return False + \ No newline at end of file diff --git a/peer2peer_file_sharing/peer.py b/peer2peer_file_sharing/peer.py new file mode 100644 index 000000000000..f057e9ea9507 --- /dev/null +++ b/peer2peer_file_sharing/peer.py @@ -0,0 +1,191 @@ +""" +P2P File Sharing Implementation +Author: Nikhil Karoriya +Description: This module implements a secure peer-to-peer file sharing algorithm +using socket programming, AES for data encryption, RSA for key exchange and Zlib for data compression + +Usage: + python peer.py --listen-port 5001 + +You will be prompted for: + + Send file (y/n)? y + Enter file path to send: sample.txt + Enter receiver's IP address: localhost (or receiver's IP address) + Enter receiver's port: 6001 +""" + + +import os +import socket +import threading +import traceback +from tqdm import tqdm +import argparse +from time import sleep +from crypto.rsa_crypto import ( + decrypt_with_rsa_private_key, + encrypt_with_rsa_public_key, + generate_rsa_key_pair, + is_valid_pem_key +) +from crypto.aes_crypto import generate_aes_key, encrypt_chunk_with_aes, decrypt_chunk_with_aes +from utils.file_utils import ensure_dir, sha256_digest_stream, is_valid_ip, is_valid_port +from utils.file_utils import CHUNK_SIZE + +PRIVATE_KEY_PATH = 'keys/private_key.pem' +PUBLIC_KEY_PATH = 'keys/public_keys.pem' +RECEIVE_DIR = 'received_files' + +ensure_dir(RECEIVE_DIR) +ensure_dir("keys") + +if not is_valid_pem_key(PRIVATE_KEY_PATH, is_private=True) or not is_valid_pem_key(PUBLIC_KEY_PATH, is_private=False): + print("\n[!] RSA key missing or invalid. Regenerating...") + generate_rsa_key_pair(PRIVATE_KEY_PATH, PUBLIC_KEY_PATH) + print("\n[+] RSA key pair regenerated.") + +parser = argparse.ArgumentParser() +parser.add_argument("--listen-port", type=int, required=True) +args = parser.parse_args() + +LISTEN_PORT = args.listen_port + +def peer_listener(): + try: + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind(('0.0.0.0', LISTEN_PORT)) + server_socket.listen(1) + print(f"\n[+] Listening on port {LISTEN_PORT}...") + + while True: + client_socket, addr = server_socket.accept() + print(f"\n\n[+] Incoming connection from {addr}\n") + + try: + key_size = int.from_bytes(client_socket.recv(4), 'big') + encrypted_key = client_socket.recv(key_size) + + name_len = int.from_bytes(client_socket.recv(4), 'big') + file_name = client_socket.recv(name_len).decode() + + extension = int.from_bytes(client_socket.recv(4), 'big') + file_extension = client_socket.recv(extension).decode() + + total_size = int.from_bytes(client_socket.recv(8), 'big') + + aes_key = decrypt_with_rsa_private_key(encrypted_key, PRIVATE_KEY_PATH) + + file_path = os.path.join(RECEIVE_DIR, file_name) + + with open(file_path, 'wb') as f_out, tqdm(total=total_size, desc=f"[+] Receiving {file_name}", unit="B", unit_scale=True) as pbar: + received_bytes = 0 + while received_bytes < total_size: + rcv_chunk_size = int.from_bytes(client_socket.recv(4), 'big') + encrypted_chunk = b"" + + while len(encrypted_chunk) < rcv_chunk_size: + part = client_socket.recv(rcv_chunk_size - len(encrypted_chunk)) + if not part: + raise Exception("\n[!] Connection lost during transfer.") + encrypted_chunk += part + + decrypted_chunk = decrypt_chunk_with_aes(encrypted_chunk, aes_key, file_extension) + f_out.write(decrypted_chunk) + received_bytes += len(decrypted_chunk) + pbar.update(len(decrypted_chunk)) + + print(f"\n[+] File saved to {file_path}") + file_hash = sha256_digest_stream(file_path) + print(f"\n[+] SHA256 Hash: {file_hash}") + + except Exception as e: + print(f"\n[!] ERROR receiving file: {str(e)}\n{traceback.format_exc()}") + finally: + client_socket.close() + + except Exception as e: + print(f"\n[!] Server failed: {str(e)}\n{traceback.format_exc()}") + +def send_file(file_path, peer_ip, peer_port): + try: + + file_name = os.path.basename(file_path) + file_extension = os.path.splitext(file_name)[1].lower() + + aes_key = generate_aes_key() + encrypted_key = encrypt_with_rsa_public_key(aes_key, PUBLIC_KEY_PATH) + file_size = os.path.getsize(file_path) + + client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + client_socket.connect((peer_ip, peer_port)) + + client_socket.sendall(len(encrypted_key).to_bytes(4, 'big')) + client_socket.sendall(encrypted_key) + + client_socket.sendall(len(file_name.encode()).to_bytes(4, 'big')) + client_socket.sendall(file_name.encode()) + + client_socket.sendall(len(file_extension.encode()).to_bytes(4, 'big')) + client_socket.sendall(file_extension.encode()) + + client_socket.sendall(file_size.to_bytes(8, 'big')) + + print() + + with open(file_path, 'rb') as f, tqdm(total=file_size, desc=f"[+] Sending {file_name}", unit="B", unit_scale=True) as pbar: + for chunk in iter(lambda: f.read(CHUNK_SIZE), b''): + encrypted_chunk = encrypt_chunk_with_aes(chunk, aes_key, file_extension) + client_socket.sendall(len(encrypted_chunk).to_bytes(4, 'big')) + client_socket.sendall(encrypted_chunk) + pbar.update(len(chunk)) + + print(f"\n[+] File '{file_name}' sent successfully to {peer_ip}:{peer_port}.") + client_socket.close() + + except Exception as e: + print(f"\n[!] Failed to send file: {str(e)}\n{traceback.format_exc()}") + + +if __name__ == '__main__': + + try: + threading.Thread(target=peer_listener, daemon=True).start() + sleep(0.5) + + while True: + user_input = input("\nSend file [y], wait [w], or exit [e]? ").strip().lower() + + if user_input == 'e': + print("\n[INFO] Exiting...") + break + + elif user_input == 'y': + file_path = input("\nEnter file path to send: ").strip() + peer_ip = input("\nEnter receiver's IP address: ").strip() + peer_port_input = input("\nEnter receiver's port: ").strip() + + if not is_valid_port(peer_port_input) or not is_valid_ip(peer_ip): + print("\n[!] Receiver IP or port not correct/specified.") + continue + + if not os.path.isfile(file_path): + print("\n[!] File does not exist.") + continue + + peer_port = int(peer_port_input) + send_file(file_path, peer_ip, peer_port) + + elif user_input == 'w': + print("\n[INFO] Waiting for incoming transfers...") + + else: + print("\n[!] Invalid input. Use 'y', 'w', or 'e'.") + + except KeyboardInterrupt: + print("\n[INFO] Exiting by keyboard interrupt.") + + except Exception as e: + print(f"\n[!] An error occurred: {str(e)}\n{traceback.format_exc()}") + + diff --git a/peer2peer_file_sharing/utils/file_utils.py b/peer2peer_file_sharing/utils/file_utils.py new file mode 100644 index 000000000000..a93a3b400ff5 --- /dev/null +++ b/peer2peer_file_sharing/utils/file_utils.py @@ -0,0 +1,36 @@ +import os +import hashlib +import ipaddress + +CHUNK_SIZE = 64 * 1024 + +def sha256_digest_stream(path: str) -> str: + + hasher = hashlib.sha256() + with open(path, 'rb') as f: + for chunk in iter(lambda: f.read(CHUNK_SIZE), b''): + hasher.update(chunk) + + return hasher.hexdigest() + +def ensure_dir(directory: str): + if not os.path.exists(directory): + os.makedirs(directory) + +def is_valid_ip(ip_str): + try: + if ip_str.strip().lower() == "localhost": + return True + ipaddress.ip_address(ip_str) + return True + + except ValueError: + return False + +def is_valid_port(port_str): + try: + port = int(port_str) + return 1 <= port <= 65535 + + except ValueError: + return False \ No newline at end of file From 7cdd1c3faded894ea401667cad2e5fbede96ee21 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 10 Oct 2025 05:58:34 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- peer2peer_file_sharing/crypto/aes_crypto.py | 28 +++-- peer2peer_file_sharing/crypto/rsa_crypto.py | 54 ++++++---- peer2peer_file_sharing/peer.py | 110 +++++++++++++------- peer2peer_file_sharing/utils/file_utils.py | 15 +-- 4 files changed, 134 insertions(+), 73 deletions(-) diff --git a/peer2peer_file_sharing/crypto/aes_crypto.py b/peer2peer_file_sharing/crypto/aes_crypto.py index 130b0124e837..5467e00d4379 100644 --- a/peer2peer_file_sharing/crypto/aes_crypto.py +++ b/peer2peer_file_sharing/crypto/aes_crypto.py @@ -2,15 +2,30 @@ from cryptography.fernet import Fernet SKIP_COMPRESSION_EXTENSIONS = { - '.zip', '.gz', '.bz2', '.xz', '.rar', '.7z', - '.jpg', '.jpeg', '.png', '.gif', '.webp', - '.mp3', '.mp4', '.avi', '.mkv', '.mov', - '.pdf' + ".zip", + ".gz", + ".bz2", + ".xz", + ".rar", + ".7z", + ".jpg", + ".jpeg", + ".png", + ".gif", + ".webp", + ".mp3", + ".mp4", + ".avi", + ".mkv", + ".mov", + ".pdf", } + def generate_aes_key(): return Fernet.generate_key() + def encrypt_chunk_with_aes(chunk: bytes, aes_key: bytes, file_extension: str) -> bytes: fernet = Fernet(aes_key) if file_extension.lower() not in SKIP_COMPRESSION_EXTENSIONS: @@ -18,9 +33,10 @@ def encrypt_chunk_with_aes(chunk: bytes, aes_key: bytes, file_extension: str) -> chunk = zlib.compress(chunk) except Exception as e: print(f"\n[!] Compression failed: {e}") - + return fernet.encrypt(chunk) + def decrypt_chunk_with_aes(chunk: bytes, aes_key: bytes, file_extension: str) -> bytes: fernet = Fernet(aes_key) try: @@ -34,4 +50,4 @@ def decrypt_chunk_with_aes(chunk: bytes, aes_key: bytes, file_extension: str) -> except zlib.error: print("\n[!] Warning: Failed to decompress — file may not be compressed") - return decrypted_data \ No newline at end of file + return decrypted_data diff --git a/peer2peer_file_sharing/crypto/rsa_crypto.py b/peer2peer_file_sharing/crypto/rsa_crypto.py index 98f599001070..269dff2ebad8 100644 --- a/peer2peer_file_sharing/crypto/rsa_crypto.py +++ b/peer2peer_file_sharing/crypto/rsa_crypto.py @@ -1,52 +1,63 @@ from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import rsa, padding + def generate_rsa_key_pair(private_path: str, public_path: str): private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) - + with open(private_path, "wb") as f: - - f.write(private_key.private_bytes( - serialization.Encoding.PEM, - serialization.PrivateFormat.TraditionalOpenSSL, - serialization.NoEncryption() - )) - + f.write( + private_key.private_bytes( + serialization.Encoding.PEM, + serialization.PrivateFormat.TraditionalOpenSSL, + serialization.NoEncryption(), + ) + ) + with open(public_path, "wb") as f: - - f.write(private_key.public_key().public_bytes( - serialization.Encoding.PEM, - serialization.PublicFormat.SubjectPublicKeyInfo - )) + f.write( + private_key.public_key().public_bytes( + serialization.Encoding.PEM, + serialization.PublicFormat.SubjectPublicKeyInfo, + ) + ) -def encrypt_with_rsa_public_key(data: bytes, public_key_path: str) -> bytes: +def encrypt_with_rsa_public_key(data: bytes, public_key_path: str) -> bytes: with open(public_key_path, "rb") as f: public_key = serialization.load_pem_public_key(f.read()) if not isinstance(public_key, rsa.RSAPublicKey): raise TypeError("\n[!] The loaded public key is not an RSA key.") - + return public_key.encrypt( data, - padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None) + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ), ) + def decrypt_with_rsa_private_key(ciphertext: bytes, private_key_path: str) -> bytes: - with open(private_key_path, "rb") as f: private_key = serialization.load_pem_private_key(f.read(), password=None) if not isinstance(private_key, rsa.RSAPrivateKey): raise TypeError("\n[!] The loaded private key is not an RSA key.") - + return private_key.decrypt( ciphertext, - padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None) + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ), ) + def is_valid_pem_key(file_path: str, is_private: bool = False) -> bool: - try: with open(file_path, "rb") as f: data = f.read() @@ -57,7 +68,6 @@ def is_valid_pem_key(file_path: str, is_private: bool = False) -> bool: else: serialization.load_pem_public_key(data) return True - + except Exception: return False - \ No newline at end of file diff --git a/peer2peer_file_sharing/peer.py b/peer2peer_file_sharing/peer.py index f057e9ea9507..bdbdf81b3ede 100644 --- a/peer2peer_file_sharing/peer.py +++ b/peer2peer_file_sharing/peer.py @@ -15,7 +15,6 @@ Enter receiver's port: 6001 """ - import os import socket import threading @@ -27,20 +26,31 @@ decrypt_with_rsa_private_key, encrypt_with_rsa_public_key, generate_rsa_key_pair, - is_valid_pem_key + is_valid_pem_key, +) +from crypto.aes_crypto import ( + generate_aes_key, + encrypt_chunk_with_aes, + decrypt_chunk_with_aes, +) +from utils.file_utils import ( + ensure_dir, + sha256_digest_stream, + is_valid_ip, + is_valid_port, ) -from crypto.aes_crypto import generate_aes_key, encrypt_chunk_with_aes, decrypt_chunk_with_aes -from utils.file_utils import ensure_dir, sha256_digest_stream, is_valid_ip, is_valid_port from utils.file_utils import CHUNK_SIZE -PRIVATE_KEY_PATH = 'keys/private_key.pem' -PUBLIC_KEY_PATH = 'keys/public_keys.pem' -RECEIVE_DIR = 'received_files' +PRIVATE_KEY_PATH = "keys/private_key.pem" +PUBLIC_KEY_PATH = "keys/public_keys.pem" +RECEIVE_DIR = "received_files" ensure_dir(RECEIVE_DIR) ensure_dir("keys") -if not is_valid_pem_key(PRIVATE_KEY_PATH, is_private=True) or not is_valid_pem_key(PUBLIC_KEY_PATH, is_private=False): +if not is_valid_pem_key(PRIVATE_KEY_PATH, is_private=True) or not is_valid_pem_key( + PUBLIC_KEY_PATH, is_private=False +): print("\n[!] RSA key missing or invalid. Regenerating...") generate_rsa_key_pair(PRIVATE_KEY_PATH, PUBLIC_KEY_PATH) print("\n[+] RSA key pair regenerated.") @@ -51,10 +61,11 @@ LISTEN_PORT = args.listen_port + def peer_listener(): try: server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - server_socket.bind(('0.0.0.0', LISTEN_PORT)) + server_socket.bind(("0.0.0.0", LISTEN_PORT)) server_socket.listen(1) print(f"\n[+] Listening on port {LISTEN_PORT}...") @@ -63,34 +74,48 @@ def peer_listener(): print(f"\n\n[+] Incoming connection from {addr}\n") try: - key_size = int.from_bytes(client_socket.recv(4), 'big') + key_size = int.from_bytes(client_socket.recv(4), "big") encrypted_key = client_socket.recv(key_size) - name_len = int.from_bytes(client_socket.recv(4), 'big') + name_len = int.from_bytes(client_socket.recv(4), "big") file_name = client_socket.recv(name_len).decode() - extension = int.from_bytes(client_socket.recv(4), 'big') + extension = int.from_bytes(client_socket.recv(4), "big") file_extension = client_socket.recv(extension).decode() - total_size = int.from_bytes(client_socket.recv(8), 'big') - + total_size = int.from_bytes(client_socket.recv(8), "big") + aes_key = decrypt_with_rsa_private_key(encrypted_key, PRIVATE_KEY_PATH) file_path = os.path.join(RECEIVE_DIR, file_name) - - with open(file_path, 'wb') as f_out, tqdm(total=total_size, desc=f"[+] Receiving {file_name}", unit="B", unit_scale=True) as pbar: + + with ( + open(file_path, "wb") as f_out, + tqdm( + total=total_size, + desc=f"[+] Receiving {file_name}", + unit="B", + unit_scale=True, + ) as pbar, + ): received_bytes = 0 while received_bytes < total_size: - rcv_chunk_size = int.from_bytes(client_socket.recv(4), 'big') + rcv_chunk_size = int.from_bytes(client_socket.recv(4), "big") encrypted_chunk = b"" - + while len(encrypted_chunk) < rcv_chunk_size: - part = client_socket.recv(rcv_chunk_size - len(encrypted_chunk)) + part = client_socket.recv( + rcv_chunk_size - len(encrypted_chunk) + ) if not part: - raise Exception("\n[!] Connection lost during transfer.") + raise Exception( + "\n[!] Connection lost during transfer." + ) encrypted_chunk += part - decrypted_chunk = decrypt_chunk_with_aes(encrypted_chunk, aes_key, file_extension) + decrypted_chunk = decrypt_chunk_with_aes( + encrypted_chunk, aes_key, file_extension + ) f_out.write(decrypted_chunk) received_bytes += len(decrypted_chunk) pbar.update(len(decrypted_chunk)) @@ -107,9 +132,9 @@ def peer_listener(): except Exception as e: print(f"\n[!] Server failed: {str(e)}\n{traceback.format_exc()}") + def send_file(file_path, peer_ip, peer_port): try: - file_name = os.path.basename(file_path) file_extension = os.path.splitext(file_name)[1].lower() @@ -120,23 +145,31 @@ def send_file(file_path, peer_ip, peer_port): client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client_socket.connect((peer_ip, peer_port)) - client_socket.sendall(len(encrypted_key).to_bytes(4, 'big')) + client_socket.sendall(len(encrypted_key).to_bytes(4, "big")) client_socket.sendall(encrypted_key) - client_socket.sendall(len(file_name.encode()).to_bytes(4, 'big')) + client_socket.sendall(len(file_name.encode()).to_bytes(4, "big")) client_socket.sendall(file_name.encode()) - client_socket.sendall(len(file_extension.encode()).to_bytes(4, 'big')) + client_socket.sendall(len(file_extension.encode()).to_bytes(4, "big")) client_socket.sendall(file_extension.encode()) - client_socket.sendall(file_size.to_bytes(8, 'big')) - + client_socket.sendall(file_size.to_bytes(8, "big")) + print() - with open(file_path, 'rb') as f, tqdm(total=file_size, desc=f"[+] Sending {file_name}", unit="B", unit_scale=True) as pbar: - for chunk in iter(lambda: f.read(CHUNK_SIZE), b''): + with ( + open(file_path, "rb") as f, + tqdm( + total=file_size, + desc=f"[+] Sending {file_name}", + unit="B", + unit_scale=True, + ) as pbar, + ): + for chunk in iter(lambda: f.read(CHUNK_SIZE), b""): encrypted_chunk = encrypt_chunk_with_aes(chunk, aes_key, file_extension) - client_socket.sendall(len(encrypted_chunk).to_bytes(4, 'big')) + client_socket.sendall(len(encrypted_chunk).to_bytes(4, "big")) client_socket.sendall(encrypted_chunk) pbar.update(len(chunk)) @@ -147,20 +180,21 @@ def send_file(file_path, peer_ip, peer_port): print(f"\n[!] Failed to send file: {str(e)}\n{traceback.format_exc()}") -if __name__ == '__main__': - +if __name__ == "__main__": try: threading.Thread(target=peer_listener, daemon=True).start() sleep(0.5) while True: - user_input = input("\nSend file [y], wait [w], or exit [e]? ").strip().lower() + user_input = ( + input("\nSend file [y], wait [w], or exit [e]? ").strip().lower() + ) - if user_input == 'e': + if user_input == "e": print("\n[INFO] Exiting...") break - elif user_input == 'y': + elif user_input == "y": file_path = input("\nEnter file path to send: ").strip() peer_ip = input("\nEnter receiver's IP address: ").strip() peer_port_input = input("\nEnter receiver's port: ").strip() @@ -176,7 +210,7 @@ def send_file(file_path, peer_ip, peer_port): peer_port = int(peer_port_input) send_file(file_path, peer_ip, peer_port) - elif user_input == 'w': + elif user_input == "w": print("\n[INFO] Waiting for incoming transfers...") else: @@ -184,8 +218,6 @@ def send_file(file_path, peer_ip, peer_port): except KeyboardInterrupt: print("\n[INFO] Exiting by keyboard interrupt.") - + except Exception as e: print(f"\n[!] An error occurred: {str(e)}\n{traceback.format_exc()}") - - diff --git a/peer2peer_file_sharing/utils/file_utils.py b/peer2peer_file_sharing/utils/file_utils.py index a93a3b400ff5..3c0133bd7099 100644 --- a/peer2peer_file_sharing/utils/file_utils.py +++ b/peer2peer_file_sharing/utils/file_utils.py @@ -4,33 +4,36 @@ CHUNK_SIZE = 64 * 1024 -def sha256_digest_stream(path: str) -> str: +def sha256_digest_stream(path: str) -> str: hasher = hashlib.sha256() - with open(path, 'rb') as f: - for chunk in iter(lambda: f.read(CHUNK_SIZE), b''): + with open(path, "rb") as f: + for chunk in iter(lambda: f.read(CHUNK_SIZE), b""): hasher.update(chunk) return hasher.hexdigest() + def ensure_dir(directory: str): if not os.path.exists(directory): os.makedirs(directory) + def is_valid_ip(ip_str): try: if ip_str.strip().lower() == "localhost": return True ipaddress.ip_address(ip_str) return True - + except ValueError: return False + def is_valid_port(port_str): try: port = int(port_str) return 1 <= port <= 65535 - + except ValueError: - return False \ No newline at end of file + return False