diff --git a/README.md b/README.md index e69de29..0865727 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,31 @@ +# youandme + +Python library to share data anonymously and securely* with limited traffic metadata. + +\* The ID one connects to a host with must be shared via a secure (private, authenticated) channel. + +`$ pip install youandme` + +# why + +In normal socket connections, Eve can see when Alex and Bob communicate and the size of their communications. + +This library sends continuous streams of data even when no information is being communicated, in order to increase unobservability of transmission times and packet sizes. + +Anonymity and encryption is provided via Tor onion services, though this library could easily be adapted to use plaintext (and encryption by an application) or + + +# security + +As stated above, this library does no authentication. However, if the ID is shared privately and safely, the tunnel will have roughly the security of a Tor v3 onion service, with increased metadata unobservability. + + +## What an attacker sees in a normal Tor connection + +![](no-dummy.png) + + +## What an attacker sees in a youandme connection + + +![](dummy.png) \ No newline at end of file diff --git a/dummy.png b/dummy.png new file mode 100644 index 0000000..60b1202 Binary files /dev/null and b/dummy.png differ diff --git a/no-dummy.png b/no-dummy.png new file mode 100644 index 0000000..0800d83 Binary files /dev/null and b/no-dummy.png differ diff --git a/setup.py b/setup.py index b390f72..4211af1 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,15 @@ from setuptools import setup, find_packages +from os import path +this_directory = path.abspath(path.dirname(__file__)) +with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: + long_description = f.read() + setup(name='youandme', version='0.0.0', - description='Unix philosophy private messages via raw pipes and metadata paranoia', + description='Simple private data sharing via bytearrays, Tor tunneling and metadata paranoia', + long_description=long_description, + long_description_content_type='text/markdown', author='Kevin Froman', author_email='beardog@mailbox.org', url='https://chaoswebs.net', diff --git a/src/yam.py b/src/yam.py index e1a5be6..976953a 100644 --- a/src/yam.py +++ b/src/yam.py @@ -23,7 +23,6 @@ def connector(host, send_data, recv_data, address="", control_port=1337, socks_p result = sock.connect_ex(('127.0.0.1', socks_port)) if result != 0: launch_tor(control_port=control_port, socks_port=socks_port) - print(host) if host: with Controller.from_port(port=control_port) as controller: controller.authenticate() @@ -39,15 +38,15 @@ def connector(host, send_data, recv_data, address="", control_port=1337, socks_p ) _Address.address = serv.service_id conn, addr = s.accept() - server(1, controller, conn, send_data, recv_data) + server(0.01, controller, conn, send_data, recv_data) else: - print('adderr', address) if not address.endswith('.onion'): address += '.onion' - client(1, address, socks_port, send_data, recv_data) + client(0.01, address, socks_port, send_data, recv_data) def chat(mode, send_data, recv_data): + display_buffer = [] if mode == 'host': while _Address.address == "": sleep(0.01) @@ -56,22 +55,32 @@ def chat(mode, send_data, recv_data): while True: try: char = chr(recv_data.pop(0)) - print('') - print(char, end='') + display_buffer.append(char) + if char == "\n" or char == "\r\n" or len(display_buffer) > 100: + #print("\033[1;33m", char, "\033[0m", end="\n") + while len(display_buffer) != 0: + #print("\033[1;33m", display_buffer.pop(0), "\033[0m", end='') + print("\033[1;33m" + display_buffer.pop(0) + "\033[0m", end="") + except IndexError: pass sleep(0.1) Thread(target=display_new, daemon=True).start() def make_message(): while True: - new = input().encode('utf-8') + new = input("\033[0m").encode('utf-8') for b in new: send_data.append(b) + send_data.append(ord(b"\n")) Thread(target=make_message, daemon=True).start() while True: - sleep(1) - - + try: + if send_data is None: + print("Well crap, we lost connection.") + break + sleep(1) + except KeyboardInterrupt: + pass if __name__ == "__main__": if len(sys.argv) >= 2: diff --git a/src/youandme/client.py b/src/youandme/client.py index 6b6a465..2af14a4 100644 --- a/src/youandme/client.py +++ b/src/youandme/client.py @@ -22,7 +22,12 @@ def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytea try: s.send(chr(to_send).encode('utf-8')) except TypeError: - s.send(to_send) + try: + if to_send is not None: + s.send(to_send) + except BrokenPipeError: + # lost connection + pass except BrokenPipeError: pass sleep(delay) diff --git a/src/youandme/server.py b/src/youandme/server.py index 86e6fea..7d08c9c 100644 --- a/src/youandme/server.py +++ b/src/youandme/server.py @@ -23,12 +23,20 @@ def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytear conn.sendall(chr(char).encode('utf-8')) except OSError: pass - + first_rec = True + WELCOME_MESSAGE = "Connection established\n" with conn: Thread(target=send_loop, daemon=True).start() while True: - data = conn.recv(1) + try: + data = conn.recv(1) + except ConnectionResetError: + break if not data: break + if first_rec: + for i in WELCOME_MESSAGE: + send_data.append(ord(i)) + first_rec = False if data != garbage_character and data: for i in data: recv_data.append(i)