Commit 5530daec authored by setop's avatar setop 🚀
Browse files

first working version

parent 7ce77237
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
\ No newline at end of file
# pylufic
# What
**pylufic** is a command line tool which allow to interact with [Let's Upload File (Lufi)](https://demo.lufi.io/about) instances, that is to download and upload client-side encrypted files.
# Why
Lufi is a web-application allowing client-side encrypted file transfers between users. Hence you don't have to trust the service provider to protect your data.
However Lufi works in a web browser, like Firefox or Chormium. When you don't want to run a full-featured graphical web browser on your machine to use it, you need a command line.
**pylufic** is a python implementation of a Lufi CLI. useful for those who already have Python in their environments.
# How
**pylufic** use the same software libraries as the Javascript version - websocket client and Standford Javascript Cryptography Library (SJCL) - but in their python implementations.
# use
## install
Be sure to have Python 3.6+ installed.
Git clone this repo (or download as zip) :
```
git clone https://framagit.org/setop/pylufic.git && cd pylufic
```
Optionally, create python virtual environment :
```
python3 -m venv .venv && . .venv/bin/activate
```
Pip install requirements (use sudo if not in a venv) :
```
pip install -r requirements.txt
```
If you want to test libraries :
```
./sjcl-test.py && ./ws-test.py
```
## help
```
./pylufic.py
```
## Upload
```
./pylufic.py file service_url
```
You may use "https://framadrop.org/" (consider donation).
## Download
```
./pylufic.py url
```
Be aware a file is opened in the current directory in append mode with the name provided in the metadata of the transfer.
## Delete
Not yet implemented
#!/usr/bin/env python3
import sys
import os
from websocket import create_connection
from json import loads, dumps
from sjcl import SJCL, sjcl
from base64 import b64decode, b64encode
MAGIC = "XXMOJOXX"
CHUNK_SIZE = 2*1000*1000
def usage():
print("download with : %s <https://service/r/id#key>" % __file__)
print("upload with : %s <filepath> <https://service/r/>" % __file__)
def upload(filepath, url):
key = b64encode(sjcl.get_random_bytes(32))
size = os.path.getsize(filepath)
(e, r) = divmod(size, CHUNK_SIZE)
totalparts = e + [0,1][r>0]
meta = { "name": filepath.split("/")[-1], "size": size, "total": totalparts, "i": 0 }
f = open(filepath, "rb")
wsurl = url.replace("http", "ws")+"upload/"
ws = create_connection(wsurl)
for (i, data) in enumerate(iter(lambda: f.read(CHUNK_SIZE), b"")):
meta["part"] = i
data = SJCL().encrypt(b64encode(data), key)
for k in data.keys():
if isinstance(data[k], bytes): # b64encode produces bytes
data[k] = data[k].decode("ascii")
ws.send(dumps(meta)+MAGIC+dumps(dumps(data)))
result = ws.recv()
print(result, file=sys.stderr)
result = loads(result)
meta["id"] = result["short"]
ws.close()
print(url+"r/"+meta["id"]+"#"+key.decode("ascii"))
def download(url):
[url, key] = url.split('#')
url = url.replace("http", "ws").replace("/r/", "/download/")
ws = create_connection(url)
p=0
t=1
while p<t:
ws.send('{"part":%d}' % p)
result = ws.recv()
idx = result.find(MAGIC)
meta = loads(result[0:idx])
print(meta, file=sys.stderr)
data = loads(loads(result[idx+len(MAGIC):]))
t = meta["total"]
f = open(meta["name"].split("/")[-1], "ab")
f.write(b64decode(SJCL().decrypt(data, key)))
p+=1
ws.close()
if __name__ == "__main__":
if len(sys.argv) == 1:
usage()
elif len(sys.argv) == 2:
download(sys.argv[1])
elif len(sys.argv) == 3:
upload(sys.argv[1], sys.argv[2])
#!/usr/bin/env python3
from json import loads, dumps
from sjcl import SJCL, sjcl
from base64 import b64decode, b64encode
if __name__ == "__main__":
key = b64encode(sjcl.get_random_bytes(32))
data = b"azertyuiopqsdfgfhjklmwxcvbn"
encrypted = SJCL().encrypt(b64encode(data), key)
for k in encrypted.keys():
if isinstance(encrypted[k], bytes): # b64encode produces bytes
encrypted[k] = encrypted[k].decode("ascii")
jsonedjsoned = dumps(dumps(encrypted))
dejsoned = loads(loads(jsonedjsoned))
assert(data == b64decode(SJCL().decrypt(dejsoned, key)))
#!/usr/bin/env python3
from websocket import create_connection
if __name__ == "__main__":
ws = create_connection("wss://echo.websocket.org")
mess = "azertyuiopqsdfgfhjklmwxcvbn"
ws.send(mess)
echo = ws.recv()
ws.close()
assert(mess == echo)
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment