cshare
A simple minimal client-encrypted online file sharing tool, inspired by Up1 and other similar projects.
- minimal amount of code (2KB when compiled and compressed), using modern Javascript features, including browser embedded crypto modules
- mandatory content expiration
- enforces maximum file size for uploads
- ships as a self-contained binary, using a SQLite database backend
- configuration via command-line options or environment variables
Shared files are downloaded, decrypted, and sent to the browser for visualization or download: there is no fancy viewer UI, preferring a native approach to content management.
Building from source
In order to build the UI you're going to need a few dependencies such as nodejs / npm:
sudo apt install golang npm brotli
go generate
go build ./cmd/cscli
go build ./cmd/cshare
This will build the cshare and cscli binaries.
Configuration
Configuration can be passed either via command-line arguments, or via environment variables. Environment variables have a prefix of CSHARE_ followed by the corresponding command-line option name, but converted to uppercase and with underscores instead of dashes, e.g. CSHARE_MAX_FILE_SIZE is equivalent to --max-file-size.
Operation
The cshare server needs write access to a filesystem path used for storage (via the --storage option), and to a SQLite database file (using the --db option). These can be located in the same directory: the file storage layer uses prefix-sharded directories, so it's not going to conflict with the database.
The server logs HTTP requests to standard output, in Apache's Combined Log format. Error messages go to stderr.
Architecture
When uploading a file, clients will generate a random cryptographic key, build a serialized data stream consisting of the file data with some additional metadata (file name, MIME type), encrypt this stream with AES (in GCM mode) and finally upload it to the server.
The server will assign a unique random file identifier to the file, and return it to the client. This identifier is then encoded together with the encryption key, to build the download token that is part of the shareable download link.
Blocking content
Every stored file is identified by a file identifier, which is part of the URL, and can be directly translated to a filesystem path (either by looking it up in the SQLite database, or by direct derivation).
File identifiers are just 20-byte strings, which are encoded in base64 when requested as part of the URL, and are encoded in base32 to generate a filesystem path (mostly to make the file names nicer to handle manually). So, it is possible for the administrators to remove content just by having the shared link, for instance:
LINK="https://cshare.example.com/#lFRtNH-8bkI0Z-G6C3kTmO6s5tD7km6FAy0r1PkKDe3aVnVPQEQ1OYq_SvNcrrOXDjU-AA=="
# extract the file identifier, in urlsafe-base64 encoding, and convert to base32
fileid=$(echo ${LINK#*#} | tr _- /+ | base64 -d | tail -c20 | base32)
rm /path/to/storage/$(echo $fileid | cut -c1)/$(echo $fileid | cut -c2)/$fileid
This is preferable to removing the corresponding entry from the SQLite database, as in that case cshare won't be able to expire the file.
Alternatively it is also possible to block HTTP requests to a specific file upstream of the cshare server:
LINK="https://cshare.example.com/#lFRtNH-8bkI0Z-G6C3kTmO6s5tD7km6FAy0r1PkKDe3aVnVPQEQ1OYq_SvNcrrOXDjU-AA=="
downloadid=$(echo ${LINK#*#} | tr _- /+ | base64 -d | tail -c20 | base64)
# this is the URL that needs to be blocked
echo "/download/$downloadid"
Maintenance
There are no specific maintenance operations to be performed, the daemon periodically expires files from storage and data from the database all by itself.
Command-line client
A command-line client for uploads, cscli, is also available. It will upload a file either from standard input or passed as an argument.
Example:
export CSHARE_SERVER=https://cshare.example.com
cscli image.png
The tool will print the download link on standard output.