20 Commits

Author SHA1 Message Date
SG
6db4849939 fixes 2023-05-12 13:43:13 +02:00
SG
260e29fbf6 Fix last chunk not received 2023-05-12 13:40:26 +02:00
SG
ef7ee52ad9 Some fixes and updates 2023-05-11 21:20:23 +02:00
SG
4e583e39c3 Change default server URL 2023-05-11 20:04:45 +02:00
SG
f36e78daf4 version bump 2023-05-08 19:27:23 +02:00
SG
8a1905a7b6 Fix progress bar handling 2023-05-08 19:18:55 +02:00
SG
71307f3bc7 updates 2023-05-08 19:03:16 +02:00
SG
99e9996a55 Remove xkcdpass requirement 2023-05-08 18:15:50 +02:00
SG
634c513c8c Switch from xkcdpass to a very simple diceware 2023-05-08 18:04:19 +02:00
SG
575568772a Reorganize files and folders 2023-05-08 17:44:34 +02:00
SG
d13b59b8e0 Reorganize files and folders 2023-05-08 17:44:16 +02:00
SG
9c385c8379 Update progress bar for smaller files 2023-05-03 18:19:53 +02:00
SG
ad17c935ef Minor fixes 2023-05-03 18:11:46 +02:00
SG
26a0840ad2 Some minor changes 2023-05-03 17:53:52 +02:00
SG
717abbc4b2 Fix some typos 2023-05-03 17:29:24 +02:00
SG
e634643141 Fix sender not exiting on last chunk 2023-05-03 17:25:59 +02:00
SG
4e0d53994c Readme 2023-05-01 17:07:50 +02:00
SG
d987dfd091 Readme 2023-05-01 17:07:09 +02:00
SG
962af5da89 Readme 2023-05-01 17:06:37 +02:00
SG
518929fe2d Readme 2023-05-01 17:04:43 +02:00
6 changed files with 65 additions and 32 deletions

View File

@@ -1,14 +1,14 @@
# Transphase
This is a collection of tools to copy files or proxy connections via WebSockets protocol.
It is done in a cryptographically safe(ish) way.
A rendevouz/relay server is used to help with data transfer.
This is a collection of tools to copy files or proxy connections via WebSockets protocol. \
It is done in a cryptographically safe(ish) way. \
A relay server is used to help with data transfer.
**Transphase** - the relay server \
**Transmat** - tool to copy files/directories \
**Transplace** - HTTP proxy/exit point
**transphase** - the relay server \
**transmat** - tool to copy files/directories \
**transplace** - HTTP proxy/exit point
### Copy files
Transphase server should be running and accessible by the parties.
### How to copy files using ```transmat```
Transphase relay server should be running and accessible by the parties.
On the sending party:
```
transmat --send <FILENAME>
@@ -18,4 +18,9 @@ This will prepare the sender and output the command to run on the receiving part
transmat --receive --password Space-Time-Continuum
```
The sending party will wait for the receiving party to connect to the relay server, and then it will start the transfer. \
With the exception of some service messages, all the data is encrypted. \
Encryption and decryption is done only client-side, and the relay server has no useful knowledge of the data it relays. \
Fernet module (AES128-CBC + HMAC-SHA256) is used to encrypt and authenticate the data.
See also ```transmat --help```

18
transmat/diceware.py Normal file

File diff suppressed because one or more lines are too long

View File

@@ -5,5 +5,4 @@ lz4==4.3.2
progress==1.6
pycparser==2.21
pyjson==1.3.0
websockets==11.0.2
xkcdpass==1.19.3
websockets==11.0.2

View File

@@ -2,15 +2,15 @@
import asyncio, websockets
import sys, os, base64, argparse, json, pickle
from xkcdpass import xkcd_password as xp
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from progress.bar import Bar
import diceware
VERSION_NUMBER="0.1"
VERSION_NUMBER="0.1.3"
SCRIPT_BASENAME = os.path.basename(sys.argv[0])
async def read_chunks(filename, chunk_size = 1024):
with open(filename, "rb") as f:
@@ -94,26 +94,23 @@ async def send_encrypted_msg(ws, k, data):
await send_msg(ws, json.dumps(msg))
async def main():
WS_RELAY_SERVER = "wss://transmat.exocortex.ru"
WS_RELAY_SERVER = "wss://transmat.exocortex.ru/ws"
parser = argparse.ArgumentParser()
arg_group = parser.add_mutually_exclusive_group(required=True)
arg_group.add_argument('--receive', '--recv', action='store_true', help='Receive a file from the remote party (mutually exclusive with --send and --relay)')
arg_group.add_argument('--send', type=str, help='Send a file to the remote party (mutually exclusive with --receive and --relay)')
arg_group.add_argument('--version', action='store_true', help="Show version")
#arg_group.add_argument('--relay', action='store_true', help='Run as a Relay server (mutually exclusive with --receive and --send)')
parser.add_argument('--server', type=str, help="Specify the Relay server URL (ignored with --relay)")
parser.add_argument('--password', type=str, help="Specify the shared password (for --receive)")
args = parser.parse_args()
passwd_part = server_part = ""
send_part = f'{sys.argv[0]} --receive '
send_part = f'{SCRIPT_BASENAME} --receive'
if args.receive:
role = 'receive'
password = args.password
if args.send and args.password is None:
wordlist = xp.generate_wordlist(wordfile = xp.locate_wordfile(), min_length = 5, max_length = 9)
password = xp.generate_xkcdpassword(wordlist, numwords=4, delimiter = "-", case='capitalize')
password = diceware.generate_passphrase(4)
passwd_part = f"--password {password}"
if args.receive and args.password is None:
print("Error: --password required when receiving files.")
@@ -128,14 +125,14 @@ async def main():
WS_RELAY_SERVER = args.server
server_part = f'--server {WS_RELAY_SERVER}'
if args.version:
print(f"{sys.argv[0]} ver {VERSION_NUMBER}")
print(f"{SCRIPT_BASENAME} ver {VERSION_NUMBER}")
sys.exit(0)
k = derive_key_from_password(password)
peer_group_id = get_peer_group_id(password)
if role == 'send':
print('Run the following command on the remote party:\n\n', send_part, server_part, passwd_part, "\n")
print('Run the following command on the remote party:\n\n', send_part, passwd_part, server_part, "\n")
filename = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
chunk_id = 0
@@ -156,11 +153,14 @@ async def main():
msg = (msgtype, peer_group_id, role, filename, chunk_size, chunk_id, number_of_chunks, chunk)
await send_encrypted_msg(ws, k, msg)
await asyncio.sleep(0.05)
chunk_id += 1
if chunk_id > number_of_chunks:
break
proceed = await ws.recv()
bar.next()
chunk_id += 1
bar.suffix = '%(percent).1f%% done'
print("\n")
bar.suffix = '%(percent).1f%% complete'
bar.update()
print("")
if role =='receive':
async with websockets.connect(WS_RELAY_SERVER) as ws:
@@ -168,8 +168,17 @@ async def main():
await send_encrypted_msg(ws, k, (msgtype, peer_group_id, role, "", "", "", "", ""))
bar = None
f = None
i = 1
i = 0
number_of_chunks = None
while True:
if number_of_chunks is not None and i > number_of_chunks:
bar.index = 100
bar.suffix = '%(percent).1f%% complete'
bar.update()
f.close()
print("")
break
message = await ws.recv()
message = json.loads(message)
payload = message["payload"]
@@ -183,16 +192,12 @@ async def main():
f.write(msg["chunk"])
else:
f.write(msg["chunk"])
i += 1
msgtype = "proceed"
await send_encrypted_msg(ws, k, (msgtype, peer_group_id, role, "", "", "", "", "")) # request the next chunk from sender
i += 1
bar.suffix = "%(percent).1f%% complete - %(eta_td)s remaining " + str(i) + "/" + str(number_of_chunks) + " msg sent"
bar.next()
if i > msg["number_of_chunks"]:
bar.suffix = '%(percent).1f%% complete'
bar.update()
f.close()
print("\n")
break
asyncio.run(main())

View File

@@ -0,0 +1,6 @@
asyncio==3.4.3
cffi==1.15.1
cryptography==40.0.2
pycparser==2.21
pyjson==1.3.0
websockets==11.0.2