My very cool projects

Go back

CipherDrop

WAAAAA! It's been at least 1.5 years since I've posted any new project on this website. What can I say, IT'S BEEN A WHILE. Today I want to write about CipherDrop. It's a little project I did 4 months ago (around the beginning of October 2024).

So, what is CipherDrop? It's a dropping place where it Ciphers! Easy, done. Let's continue

Nah but on a serious note, it's a free & open source file sharing service. I wanted to create this to practice Rust a little bit. It doesn't support chunking and such, so the file upload limit is 1GB. (I could do file chunking but that's mostly JavaScript on the client side. As I said, this was to practice Rust!)

The idea was to make it fully private. Privacy first! So, the files that you upload get encrypted by a random key generated in your browser. The key never gets shared with the server, or sent to the server in any way. When you want to download again, the key gets read from the URL (in the fragment part), like so: https://example.com/download/file#SOME_PRIVATE_KEY. The very sensitive private key part never gets sent to the server by the browser, since it's behind the #.

Databasé

The use of a database is totally unnecessary here. Reflecting towards the development process now (4 months later), I could easily keep track of the files based on the file hashes. Still, the idea was to eventually have the possibility to have multiple S3 buckets in the database, and that the program would pick an S3 bucket. Whatever, never got that far !

For the database I chose PostgreSQL, it could've been any database at this point, but I had the Docker compose lines for a Postgres database ready from a different project. So I just copy pasted it around. For at Rust, I decided to use Diesel ORM. It just seems really nice with the migrations, models & actions. Everything just seems so obvious!

There are basically just two tables, here are the schemes generated by Diesel:

Showing little shemes working together

S3 Buckéts

Buckets ! Bucketss !!

I already said before that this project was to practice Rust with. But I also wanted an excuse to try some things with S3 buckets.

I was using the rust-s3crate, which is a little weird. I had my S3 bucket at Hetzner, which gave me this link: my_bucket.fsn1.your-objectstorage.com. To initialise the crate with a different S3 provider other than AWS, you needed to provide the following data:

NAME: my_bucket.fsn1,
REGION: fsn1,
ENDPOINT: your-objectstorage.com,
ACCESS_KEY: some access key,
SECRET_KEY: some secret key

The thing that absolutely fricking annoyed me was the region having to be in the name parameter. The region parameter (fsn1) doesn't do ANYTHING. At first I didn't have the region included in the bucket name, and it failed to connect to the bucket. After some debugging I found out the crate doesn't actually use the region parameter if you use a custom S3 provider. Annoying as hell! It literally doesn't make sense to me. I've searched through the source of the crate itself, and I found the culprit.

Showing the line I found in the GitHub project

It literally doesn't make sense to me, it just doesn't, DOES NOT, use the region parameter. It just pastes the name & endpoint together, fuck the region I guess? And I just wanted to quickly note, yes, I've searched for this, yes I've gone through the crate files, yes this probably took me a few hours, no I won't be creating a PR on this.

After that was handled, everything was pretty simple.

Témplating

Frontend... my favourite... (not)

We use templating! I never used Tera, or just any other templating framework before. It's pretty chill honestly. Just HTML and put a few quirky lines in, and suddenly the content of the page is dynamic. We have to obviously show what file you're about the download, and if it's available, and if it's available, and you know, if it's available (there's actually not much data to work with)

Either way, I really liked how Tera works.

{% if success %}
    <div class="wrapper file">
        <small>
            You're about to download
        </small>
        <h3>
            {{file_name}}
        </h3>

        <div class="downloader">
            <button>
                Download
            </button>

            <div class="loader hidden">
                <div class="inner"></div>
            </div>

            <p class="error hidden">
                Wrong!
            </p>

            <p class="info hidden"></p>
        </div>

        <small class="availability"></small>

        <input type="hidden" id="uuid" value="{{uuid}}">
        <input type="hidden" id="available_till" value="{{available_till}}">
        <input type="hidden" id="iv" value="{{iv}}">
        <input type="hidden" id="key" value="{{key}}">
        <input type="hidden" id="mime_type" value="{{mime_type}}">
        <input type="hidden" id="file_name" value="{{file_name}}">
    </div>
{% else %}
    <div class="wrapper">
        <h3 class="nf">
            Could not find file
        </h3>

        <small>
            The file could've expired or just never existed in the first place.
        </small>
    </div>
{% endif %}

You see how simple it looks? It's even possible to just create hidden inputs with the data from the database for later processing when downloading the file. It's perfect!

Hosting(é)

Hosting the application was interesting. I wanted this to be privacy first too. So, what did I do? I bought a VPS from a hosting provider who guarantees anonymity. Turned off all access & error logs, and hosted the application at cipherdrop.sh. I also hosted a tor service mirror, that might've been a mistake. Within two weeks of hosting the domain got blacklisted by multiple services like Spamhaus. This is what I wrote about it in the GitHub repository:

The domain I had (cipherdrop.sh) got blacklisted/blocked by multiple services like Spamhaus. While I firmly believe CipherDrop itself isn't a bad service and that privacy is a fundamental right, I've decided to take this offline. I encourage anyone interested to set it up again using the details provided here. All the code and documentation remain available for anyone who shares the same vision for anonymous and secure file hosting.

Anyhow, this is all for today, if you want to see the full code & documentation, Take a look at the repository (it's free)