{"id":26093168,"url":"https://github.com/davidesantangelo/lanet","last_synced_at":"2025-04-12T08:33:11.671Z","repository":{"id":281015402,"uuid":"943803326","full_name":"davidesantangelo/lanet","owner":"davidesantangelo","description":"Lanet: A lightweight tool for secure and easy peer-to-peer communication on local area networks.  Includes a CLI and Ruby API.","archived":false,"fork":false,"pushed_at":"2025-03-20T08:11:00.000Z","size":188,"stargazers_count":20,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-05T23:27:13.286Z","etag":null,"topics":["api","cli","networking","ruby"],"latest_commit_sha":null,"homepage":"https://davidesantangelo.github.io/lanet/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidesantangelo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"davidesantangelo","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-03-06T09:41:11.000Z","updated_at":"2025-03-23T08:07:41.000Z","dependencies_parsed_at":"2025-03-06T14:53:08.832Z","dependency_job_id":"6fc7ecb2-5345-40bd-85b1-ac54f59d28af","html_url":"https://github.com/davidesantangelo/lanet","commit_stats":null,"previous_names":["davidesantangelo/lanet"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidesantangelo%2Flanet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidesantangelo%2Flanet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidesantangelo%2Flanet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidesantangelo%2Flanet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidesantangelo","download_url":"https://codeload.github.com/davidesantangelo/lanet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248540445,"owners_count":21121359,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","cli","networking","ruby"],"created_at":"2025-03-09T11:55:45.481Z","updated_at":"2025-04-12T08:33:11.665Z","avatar_url":"https://github.com/davidesantangelo.png","language":"Ruby","readme":"# Lanet\n\n[![Gem Version](https://img.shields.io/gem/v/lanet?style=flat)](https://rubygems.org/gems/lanet)\n[![Gem Total Downloads](https://img.shields.io/gem/dt/lanet?style=flat)](https://rubygems.org/gems/lanet)\n[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\nA lightweight, powerful LAN communication tool that enables secure message exchange between devices on the same network. Lanet makes peer-to-peer networking simple with built-in encryption, network discovery, and both targeted and broadcast messaging capabilities.\n\n## Features\n\n- **Simple API** - An intuitive Ruby interface makes network communication straightforward.\n- **Built-in encryption** - Optional message encryption with AES-256-GCM for confidentiality.\n- **Network scanning** - Automatically discover active devices on your local network.\n- **Targeted messaging** - Send messages to specific IP addresses.\n- **Broadcasting** - Send messages to all devices on the network.\n- **Host pinging** - Check host availability and measure response times (with a familiar `ping` interface).\n- **Command-line interface** - Perform common network operations directly from your terminal.\n- **Extensible** - Easily build custom tools and integrations using the Lanet API.\n- **Configurable:**  Adjust port settings, encryption keys, and network scan ranges.\n- **Digital Signatures**: Ensure message authenticity and integrity\n- **File Transfers**: Securely send encrypted files over the LAN with progress tracking and integrity verification\n- **Mesh Networking**: Create resilient mesh networks for decentralized communication, enabling messages to be routed through multiple hops without central infrastructure\n- **Advanced Traceroute**: Analyze network paths using multiple protocols (ICMP, UDP, and TCP) with intelligent fallback mechanisms\n\n## Security Features\n\n### Encryption\n\nLanet uses AES-256-CBC encryption to protect the content of messages. This ensures confidentiality during transmission.\n\n### Digital Signatures\n\nDigital signatures provide:\n- **Authentication**: Verify the identity of the message sender\n- **Data Integrity**: Ensure the message hasn't been tampered with during transit\n- **Non-repudiation**: Senders cannot deny sending a message they signed\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'lanet'\n```\n\nAnd then execute:\n\n```bash\nbundle install\n```\n\nOr install it yourself as:\n\n```bash\ngem install lanet\n```\n\n## Usage\n\n### Command Line Interface\n\nLanet provides a powerful CLI for common network operations:\n\n#### Generating Signature Keys\n\nGenerate a key pair for digital signatures:\n\n```bash\nlanet keygen\n```\n\nGenerate a key pair with specific options:\n\n```bash\nlanet keygen --bits 4096 --output ~/.lanet_keys\n```\n\nThe command will generate two files:\n- `lanet_private.key`: Keep this secure and don't share it\n- `lanet_public.key`: Share this with others who need to verify your messages\n\n#### Sending Signed Messages\n\nSend a digitally signed message (without encryption):\n\n```bash\nlanet send --target 192.168.1.5 --message \"Signed message\" --private-key-file lanet_private.key\n```\n\nSend an encrypted and signed message:\n\n```bash\nlanet send --target 192.168.1.5 --message \"Secure signed message\" --key \"my_secret_key\" --private-key-file lanet_private.key\n```\n\nBroadcast a signed message to all devices:\n\n```bash\nlanet broadcast --message \"Important announcement\" --private-key-file lanet_private.key\n```\n\n#### Receiving and Verifying Signed Messages\n\nListen for messages and verify signatures:\n\n```bash\nlanet listen --public-key-file lanet_public.key\n```\n\nListen for encrypted and signed messages:\n\n```bash\nlanet listen --encryption-key \"my_secret_key\" --public-key-file lanet_public.key\n```\n\nWhen a signed message is received, the output will show verification status:\n\n```\nMessage from 192.168.1.5:\nContent: Hello, this is a signed message\nSignature: VERIFIED\n----------------------------------------\n```\n\nIf signature verification fails:\n\n```\nMessage from 192.168.1.5:\nContent: Hello, this message was tampered with\nSignature: NOT VERIFIED: Signature verification failed\n----------------------------------------\n```\n\n#### Scanning the network\n\n```bash\nlanet scan --range 192.168.1.0/24\n```\n\nWith verbose output (shows detailed host information):\n```bash\nlanet scan --range 192.168.1.0/24 --verbose\n```\n\nControl scan performance with threads:\n```bash\nlanet scan --range 192.168.1.0/24 --threads 16 --timeout 2\n```\n\nThe scanner employs multiple detection methods to find active hosts:\n- TCP port connection attempts\n- ICMP ping requests\n- UDP packet probing\n- ARP table lookups\n\nVerbose scanning provides rich device information:\n```\nIP: 192.168.1.1\nHostname: router.home\nMAC: a4:2b:b0:8a:5c:de\nResponse time: 5.23ms\nDetection method: TCP\nOpen ports:\n  - 80: HTTP\n  - 443: HTTPS\n  - 22: SSH\n```\n\nScanning shows real-time progress for tracking large network scans:\n```\nScanning network: 67.5% complete (162/240)\n```\n\n#### Sending a message to a specific target\n\n```bash\nlanet send --target 192.168.1.5 --message \"Hello there!\"\n```\n\n#### Sending an encrypted message\n\n```bash\nlanet send --target 192.168.1.5 --message \"Secret message\" --key \"my_secret_key\"\n```\n\n#### Broadcasting a message to all devices\n\n```bash\nlanet broadcast --message \"Announcement for everyone!\"\n```\n\n#### Listening for incoming messages\n\n```bash\nlanet listen\n```\n\n#### Listening for encrypted messages\n\n```bash\nlanet listen --key \"my_secret_key\"\n```\n\n#### Pinging a specific host\n\nYou can ping a host using either of these formats:\n\n```bash\n# Simple format\nlanet ping 192.168.1.5\n\n# Option format\nlanet ping --host 192.168.1.5\n```\n\nThe ping command displays real-time responses just like the standard ping utility:\n\n```\nPING 192.168.1.5 (192.168.1.5): 56 data bytes\n64 bytes from 192.168.1.5: icmp_seq=0 ttl=64 time=2.929 ms\n64 bytes from 192.168.1.5: icmp_seq=1 ttl=64 time=2.845 ms\n64 bytes from 192.168.1.5: icmp_seq=2 ttl=64 time=3.069 ms\n64 bytes from 192.168.1.5: icmp_seq=3 ttl=64 time=3.090 ms\n64 bytes from 192.168.1.5: icmp_seq=4 ttl=64 time=3.228 ms\n\n--- 192.168.1.5 ping statistics ---\n5 packets transmitted, 5 packets received, 0.0% packet loss\nround-trip min/avg/max/stddev = 2.845/3.032/3.228/0.134 ms\n```\n\n#### Pinging multiple hosts\n\n```bash\n# Option format with multiple hosts\nlanet ping --hosts 192.168.1.5,192.168.1.6,192.168.1.7 --timeout 2 --count 5\n```\n\nFor only showing ping summaries:\n\n```bash\n# Simple format with quiet option\nlanet ping 192.168.1.5 --quiet\n\n# Option format with quiet option\nlanet ping --host 192.168.1.5 --quiet\n```\n\n#### Continuous ping (like traditional ping)\n\nPing continuously until manually interrupted (Ctrl+C):\n\n```bash\n# Simple format with continuous option\nlanet ping 192.168.1.5 --continuous\n\n# Option format with continuous option\nlanet ping --host 192.168.1.5 --continuous\n```\n\nPing continuously with custom timeout:\n\n```bash\nlanet ping 192.168.1.5 --continuous --timeout 2\n```\n\nPing multiple hosts continuously:\n\n```bash\nlanet ping --hosts 192.168.1.5,192.168.1.6 --continuous\n```\n\n#### Sending Files Securely\n\nSend files with encryption:\n\n```bash\nlanet send-file --target 192.168.1.5 --file document.pdf --key \"my_secret_key\"\n```\n\nSend files with encryption and digital signatures:\n\n```bash\nlanet send-file --target 192.168.1.5 --file document.pdf --key \"my_secret_key\" --private-key-file lanet_private.key\n```\n\n#### Receiving Files\n\nListen for incoming files:\n\n```bash\nlanet receive-file --output ./downloads\n```\n\nReceive encrypted files:\n\n```bash\nlanet receive-file --output ./downloads --encryption-key \"my_secret_key\"\n```\n\nReceive encrypted files with signature verification:\n\n```bash\nlanet receive-file --output ./downloads --encryption-key \"my_secret_key\" --public-key-file lanet_public.key\n```\n\n#### Mesh Networking\n\nCreate a decentralized mesh network where devices can communicate even without direct connectivity:\n\n```bash\n# Start a mesh network node\nlanet mesh start\n\n# Start a mesh network node with custom settings\nlanet mesh start --port 5050 --max-hops 15\n```\n\nSend messages through the mesh network:\n\n```bash\n# Send a message through the mesh network to a specific node ID\nlanet mesh send --target a1b2c3d4-5678-90ef-ghij --message \"Hello Mesh Network\"\n\n# Send an encrypted message through the mesh network\nlanet mesh send --target a1b2c3d4-5678-90ef-ghij --message \"Secret mesh message\" --key \"secret-key\"\n\n# Send a signed message through the mesh network\nlanet mesh send --target a1b2c3d4-5678-90ef-ghij --message \"Authenticated mesh message\" --private-key-file lanet_private.key\n```\n\nView information about your mesh network:\n\n```bash\n# Display information about mesh network connections\nlanet mesh info\n```\n\n#### Tracing the route to a target host\n\nBasic traceroute using UDP (default protocol):\n\n```bash\n# Simple format\nlanet traceroute google.com\n\n# Option format\nlanet traceroute --host google.com\n```\n\nTrace using ICMP protocol:\n\n```bash\nlanet traceroute --host google.com --protocol icmp\n```\n\nTrace using TCP protocol:\n\n```bash\nlanet traceroute --host google.com --protocol tcp --max-hops 15\n```\n\nCustomize traceroute parameters:\n\n```bash\nlanet traceroute --host github.com --protocol tcp --max-hops 20 --timeout 2 --queries 4\n```\n\n### Ruby API\n\nYou can also use Lanet programmatically in your Ruby applications:\n\n```ruby\nrequire 'lanet'\n\n# Create a scanner and find active devices\nscanner = Lanet.scanner\nactive_ips = scanner.scan('192.168.1.0/24')\nputs \"Found devices: #{active_ips.join(', ')}\"\n\n# Scan with verbose option for detailed output\ndetailed_hosts = scanner.scan('192.168.1.0/24', 1, 32, true)\ndetailed_hosts.each do |host|\n  puts \"Host: #{host[:ip]}, Hostname: #{host[:hostname]}, Response Time: #{host[:response_time]}ms\"\n  puts \"Open ports: #{host[:ports].map { |port, service| \"#{port} (#{service})\" }.join(', ')}\" if host[:ports]\nend\n\n# Customize scanning performance with timeout and thread count\nactive_ips = scanner.scan('192.168.1.0/24', 0.5, 16)  # 0.5 second timeout, 16 threads\n\n# Send a message to a specific IP\nsender = Lanet.sender\nsender.send_to('192.168.1.5', 'Hello from Ruby!')\n\n# Broadcast a message to all devices\nsender.broadcast('Announcement to all devices!')\n\n# Listen for incoming messages\nreceiver = Lanet.receiver\nreceiver.listen do |data, ip|\n  puts \"Received from #{ip}: #{data}\"\nend\n\n# Work with encrypted messages\nencrypted = Lanet.encrypt('Secret message', 'my_encryption_key')\ndecrypted = Lanet.decrypt(encrypted, 'my_encryption_key')\n\n# Ping a specific host\npinger = Lanet.pinger\nresult = pinger.ping_host('192.168.1.5')\nputs \"Host reachable: #{result[:status]}\"\nputs \"Response time: #{result[:response_time]}ms\"\n\n# Ping a specific host with real-time output\npinger = Lanet.pinger(timeout: 2, count: 5)\nresult = pinger.ping_host('192.168.1.5', true) # true enables real-time output\n\n# Ping continuously until interrupted\npinger = Lanet.pinger\npinger.ping_host('192.168.1.5', true, true) # true, true enables real-time continuous output\n\n# Ping without real-time output (for programmatic use)\nresult = pinger.ping_host('192.168.1.5')\nputs \"Host reachable: #{result[:status]}\"\nputs \"Response time: #{result[:response_time]}ms\"\n\n# Check if a host is reachable\nif pinger.reachable?('192.168.1.5')\n  puts \"Host is up!\"\nelse\n  puts \"Host is down!\"\nend\n\n# Ping multiple hosts\nresults = pinger.ping_hosts(['192.168.1.5', '192.168.1.6', '192.168.1.7'])\nresults.each do |host, result|\n  status = result[:status] ? \"up\" : \"down\"\n  puts \"#{host} is #{status}. Response time: #{result[:response_time] || 'N/A'}\"\nend\n\n# Ping multiple hosts continuously\npinger.ping_hosts(['192.168.1.5', '192.168.1.6'], true, true)\n\n# Work with secure file transfers\nfile_transfer = Lanet.file_transfer\nfile_transfer.send_file('192.168.1.5', 'document.pdf', 'encryption_key') do |progress, bytes, total|\n  puts \"Progress: #{progress}% (#{bytes}/#{total} bytes)\"\nend\n\n# Receive files\nfile_transfer.receive_file('./downloads', 'encryption_key') do |event, data|\n  case event\n  when :start\n    puts \"Receiving file: #{data[:file_name]} from #{data[:sender_ip]}\"\n  when :progress\n    puts \"Progress: #{data[:progress]}%\"\n  when :complete\n    puts \"File saved to: #{data[:file_path]}\"\n  end\nend\n\n# Mesh Networking\nmesh = Lanet.mesh_network\nmesh.start  # Start the mesh node and discovery service\n\n# Send a message through the mesh network\nmesh.send_message(target_node_id, \"Hello through the mesh!\", \"optional-encryption-key\")\n\n# Get info about mesh connections\nputs \"Node ID: #{mesh.node_id}\"\nputs \"Connected to #{mesh.connections.size} nodes\"\nmesh.connections.each do |node_id, info|\n  puts \"  #{node_id} (#{info[:ip]})\"\nend\n\n# Properly stop the mesh node\nmesh.stop\n\n# Trace route to a host with different protocols\ntracer = Lanet.traceroute(protocol: :udp)\nhops = tracer.trace('github.com')\nhops.each do |hop|\n  puts \"Hop #{hop[:ttl]}: #{hop[:ip]} - Response: #{hop[:avg_time]}ms\"\nend\n\n# Use TCP protocol with custom parameters\ntcp_tracer = Lanet.traceroute(protocol: :tcp, max_hops: 15, timeout: 2)\ntcp_tracer.trace('google.com')\n```\n\n## Mesh Network\n\nThe mesh networking feature provides decentralized communication capabilities:\n\n- **Auto-discovery**: Nodes automatically find each other on the network\n- **Multi-hop routing**: Messages can be routed through intermediate nodes\n- **Self-healing**: Adapts to changing network conditions and lost connections\n- **Store and forward**: Messages persist until they can be delivered\n- **End-to-end security**: Messages remain encrypted across multiple hops\n- **Verification**: Digital signatures ensure message integrity through the mesh\n\nIdeal for:\n- IoT networks where devices may not have direct connectivity\n- Ad-hoc networks without fixed infrastructure\n- Networks requiring high resilience and redundancy\n- Applications needing peer-to-peer communication\n\n## Configuration\n\nLanet can be configured with several options:\n\n- **Port**: Default is 5000, but can be changed for both sending and receiving\n- **Encryption Keys**: Use your own encryption keys for secure communication\n- **Custom Ranges**: Scan specific network ranges to discover devices\n\n## Use Case Example: Small Office Network Monitoring\n\nThis example demonstrates how Lanet can be used to create a simple network monitoring system for a small office, checking device availability and sending notifications when issues are detected.\n\n```ruby\nrequire 'lanet'\nrequire 'json'\nrequire 'terminal-notifier' if Gem::Platform.local.os == 'darwin'\n\nclass NetworkMonitor\n  def initialize(config_file = 'network_config.json')\n    @config = JSON.parse(File.read(config_file))\n    @scanner = Lanet.scanner\n    @sender = Lanet.sender\n    @pinger = Lanet.pinger(timeout: 1, count: 3)\n    @last_status = {}\n    \n    puts \"Network Monitor initialized for #{@config['network_name']}\"\n    puts \"Monitoring #{@config['devices'].size} devices on #{@config['network_range']}\"\n  end\n  \n  def scan_network\n    puts \"\\n=== Full Network Scan: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')} ===\"\n    results = @scanner.scan(@config['network_range'], 1, 32, true)\n    \n    # Find unexpected devices\n    known_ips = @config['devices'].map { |d| d['ip'] }\n    unknown_devices = results.reject { |host| known_ips.include?(host[:ip]) }\n    \n    if unknown_devices.any?\n      puts \"\\n⚠️ Unknown devices detected on network:\"\n      unknown_devices.each do |device|\n        puts \"  - IP: #{device[:ip]}, Hostname: #{device[:hostname] || 'unknown'}\"\n      end\n      \n      # Alert admin about unknown devices\n      message = \"#{unknown_devices.size} unknown devices found on network!\"\n      notify_admin(message)\n    end\n    \n    results\n  end\n  \n  def monitor_critical_devices\n    puts \"\\n=== Checking Critical Devices: #{Time.now.strftime('%H:%M:%S')} ===\"\n    \n    @config['devices'].select { |d| d['critical'] == true }.each do |device|\n      result = @pinger.ping_host(device['ip'])\n      current_status = result[:status]\n      \n      if @last_status[device['ip']] != current_status\n        status_changed(device, current_status)\n      end\n      \n      @last_status[device['ip']] = current_status\n      \n      status_text = current_status ? \"✅ ONLINE\" : \"❌ OFFLINE\"\n      puts \"#{device['name']} (#{device['ip']}): #{status_text}\"\n      puts \"  Response time: #{result[:response_time]}ms\" if current_status\n    end\n  end\n  \n  def status_changed(device, new_status)\n    message = if new_status\n                \"🟢 #{device['name']} is back ONLINE\"\n              else\n                \"🔴 ALERT: #{device['name']} (#{device['ip']}) is DOWN!\"\n              end\n    \n    puts \"\\n#{message}\\n\"\n    notify_admin(message)\n    \n    # Send notification to all network admin devices\n    @config['admin_devices'].each do |admin_device|\n      @sender.send_to(admin_device['ip'], message)\n    end\n  end\n  \n  def notify_admin(message)\n    # Send desktop notification on macOS\n    if Gem::Platform.local.os == 'darwin'\n      TerminalNotifier.notify(message, title: 'Network Monitor Alert')\n    end\n    \n    # You could also add SMS, email, or other notification methods here\n  end\n  \n  def run_continuous_monitoring\n    # Initial full network scan\n    scan_network\n    \n    puts \"\\nStarting continuous monitoring (press Ctrl+C to stop)...\"\n    \n    # Set up a listener for incoming alerts\n    receiver_thread = Thread.new do\n      receiver = Lanet.receiver\n      receiver.listen do |message, source_ip|\n        puts \"\\n📨 Message from #{source_ip}: #{message}\"\n      end\n    end\n    \n    # Main monitoring loop\n    loop do\n      monitor_critical_devices\n      \n      # Full network scan every hour\n      scan_network if Time.now.min == 0\n      \n      sleep @config['check_interval']\n    end\n  rescue Interrupt\n    puts \"\\nMonitoring stopped.\"\n  ensure\n    receiver_thread.kill if defined?(receiver_thread) \u0026\u0026 receiver_thread\n  end\nend\n\n# Example configuration file (network_config.json):\n# {\n#   \"network_name\": \"Office Network\",\n#   \"network_range\": \"192.168.1.0/24\",\n#   \"check_interval\": 300,\n#   \"devices\": [\n#     {\"name\": \"Router\", \"ip\": \"192.168.1.1\", \"critical\": true},\n#     {\"name\": \"File Server\", \"ip\": \"192.168.1.10\", \"critical\": true},\n#     {\"name\": \"Printer\", \"ip\": \"192.168.1.20\", \"critical\": false}\n#   ],\n#   \"admin_devices\": [\n#     {\"name\": \"IT Manager Laptop\", \"ip\": \"192.168.1.100\"}\n#   ]\n# }\n\n# Usage:\n# monitor = NetworkMonitor.new('network_config.json')\n# monitor.run_continuous_monitoring\n```\n\n## Use Case Example: Securely Sharing Files in a Team Environment\n\nThis example demonstrates how to use Lanet's file transfer capabilities to securely share files within a team:\n\n```ruby\nrequire 'lanet'\nrequire 'fileutils'\n\nclass SecureTeamFileSharing\n  def initialize(team_key, keys_dir = '~/.lanet_keys')\n    @team_key = team_key\n    @keys_dir = File.expand_path(keys_dir)\n    @transfer = Lanet.file_transfer\n    \n    # Ensure keys directory exists\n    FileUtils.mkdir_p(@keys_dir) unless Dir.exist?(@keys_dir)\n    \n    # Generate keys if they don't exist\n    unless File.exist?(private_key_path) \u0026\u0026 File.exist?(public_key_path)\n      puts \"Generating new key pair for secure file sharing...\"\n      key_pair = Lanet::Signer.generate_key_pair\n      File.write(private_key_path, key_pair[:private_key])\n      File.write(public_key_path, key_pair[:public_key])\n      puts \"Keys generated successfully.\"\n    end\n    \n    # Load the private key\n    @private_key = File.read(private_key_path)\n  end\n  \n  def share_file(target_ip, file_path)\n    unless File.exist?(file_path)\n      puts \"Error: File not found: #{file_path}\"\n      return false\n    end\n    \n    puts \"Sharing file: #{File.basename(file_path)} (#{File.size(file_path)} bytes)\"\n    puts \"Target: #{target_ip}\"\n    puts \"Security: Encrypted with team key and digitally signed\"\n    \n    begin\n      @transfer.send_file(target_ip, file_path, @team_key, @private_key) do |progress, bytes, total|\n        print \"\\rProgress: #{progress}% (#{bytes}/#{total} bytes)\"\n      end\n      puts \"\\nFile shared successfully!\"\n      true\n    rescue StandardError =\u003e e\n      puts \"\\nError sharing file: #{e.message}\"\n      false\n    end\n  end\n  \n  def start_receiver(output_dir = './shared_files')\n    FileUtils.mkdir_p(output_dir) unless Dir.exist?(output_dir)\n    puts \"Listening for incoming files...\"\n    puts \"Files will be saved to: #{output_dir}\"\n    \n    @transfer.receive_file(output_dir, @team_key, File.read(public_key_path)) do |event, data|\n      case event\n      when :start\n        puts \"\\nIncoming file: #{data[:file_name]} from #{data[:sender_ip]}\"\n        puts \"Size: #{data[:file_size]} bytes\"\n      when :progress\n        print \"\\rReceiving: #{data[:progress]}% complete\"\n      when :complete\n        puts \"\\nFile received: #{data[:file_path]}\"\n        puts \"Signature verified: Authentic file from team member\"\n      when :error\n        puts \"\\nError: #{data[:error]}\"\n      end\n    end\n  end\n  \n  private\n  \n  def private_key_path\n    File.join(@keys_dir, 'team_private.key')\n  end\n  \n  def public_key_path\n    File.join(@keys_dir, 'team_public.key')\n  end\nend\n\n# Usage:\n# sharing = SecureTeamFileSharing.new(\"team-secret-key-123\")\n#\n# To share a file:\n# sharing.share_file(\"192.168.1.5\", \"important_document.pdf\")\n#\n# To receive files:\n# sharing.start_receiver(\"./team_files\")\n```\n\nThis example:\n- Creates a secure file sharing system with end-to-end encryption\n- Uses team-wide encryption key for confidentiality\n- Implements digital signatures to verify file authenticity\n- Provides real-time progress tracking for both sending and receiving files\n- Handles errors gracefully with user-friendly messages\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/davidesantangelo/lanet. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/davidesantangelo/lanet/blob/master/CODE_OF_CONDUCT.md).\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Lanet project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/davidesantangelo/lanet/blob/master/CODE_OF_CONDUCT.md).\n","funding_links":["https://github.com/sponsors/davidesantangelo"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidesantangelo%2Flanet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidesantangelo%2Flanet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidesantangelo%2Flanet/lists"}