Data leaks, hacks and identity fraud have been a regularity in the daily news for the past years. Even governments and universities struggle with getting their systems secured and compliant. Existing solutions are either hard-to-use (even for experts) or not so privacy-conscious after all.
What is Cryptify
Cryptify is an easy-to-use file transfer application that makes use of authenticated end-to-end encryption. Next to the file(s) you would like to send, it asks you to provide your e-mail address and the e-mail address of the recipient. Optionally you can type a message which is sent to the recipient along with the corresponding download link.
Before uploading the files to the server, Cryptify will encrypt your documents using the Identity Based Encryption service IRMAseal. As the identity, the recipients' email address is used, ensuring that only the recipient can decrypt the files. In order to do so, after the recipient clicked the download link received by email, they will need to use the IRMA app on their phone to scan a QR code and prove, using IRMA, that they are the intended recipient. Cryptify will then download the encrypted files and decrypt them right before they hit the download folder.
Because the encryption and decryption happens in the internet browser of the user, files will never leave their computer unencrypted. Furthermore, files are deleted two weeks after upload, so even in the unlikely event that a server gets hacked, there won't be anything (left) to steal.
What did we do in this project?
Our friends at the Privacy by Design foundation asked us to build the backend for the Cryptify application. Since the frontend is written in TypeScript, they asked us to build the backend using TypeScript as well. The API design is simple. Since no stable browsers yet support streaming request bodies we had to upload the files in a chunked manner. Downloads can occur streaming, so therefore only one endpoint is needed. Combined, resulting in the following routes:
/fileupload/init /fileupload/:uuid /fileupload/finalize/:uuid /filedownload/:uuid
The first call, to
init, returns a so-called unique identifier (
uuid) to keep track off your transfer. In the subsequent calls, this
uuid is incorporated when uploading, finalizing and for the recipient when downloading the files. When uploading a chunk, the information is verified using a hash of the uploaded chunk. Of course, this is all hidden for the end-user, in order to keep the application easy to use.
nodemailer, which is a single module with zero dependencies. This was a practical decision, since implementing SMTP and all related security measures sounds like a lot of extra work in which a lot can go wrong.
To keep track of the files, no database is used. Instead, for every file that is uploaded, a metadata file is created next to it in which only the minimally needed information to process the transfer is stored (e.g. sender, recipient, expiration, filesize). This data is deleted alongside the file on expiration.
The repository of the project, more specifically of the back-end, can be found here.
As a future improvement we have implemented an alternative backend in our favourite programming language: Rust. After some testing we found that Rust implementation is more efficient and reliable than the Node.js implementation.
We will submit a PR for this alternative in the near future.
Try it out!
Can't you wait to check it out? Cryptify is available as a beta right now at https://cryptify.nl. This version will be available for at least a few more months, so try it out now and let us know what you think!
If you liked this blog, you might also like this talk at the IRMA meetup, looking at, among other things, the user-experience aspects of Cryptify: https://www.youtube.com/watch?v=s3deWHy1uSc