Working on Zentrox vault

📆 6/15/24 - 6/20/24 • 🔗 Zentrox

Intro

I have been working on a project called Zentrox (which you really should star) for a while now.
This project lets you set up a server admin-dashboard on your home server, laptop...
By now, some of the features are already partially done. i.e A FTP server, system stats overview,...
Another part of Zentrox is "Vault".

What is Vault

Vault will let you set up a simple but secure folder on your server.
In this folder, you can store private files like photos, documents,...
It is/will be integrated with Zentrox by default and place under Storage > Vault.

How does it work


⚠️ This may all change 👇

6/15/24

Firstly, the user has to configure a key for Zentrox Vault.
Vault will then take the key and perform hashing on it for 1000 times. That way, it will be very hard to brute force the password later, as the hashing takes a bit of time and would slow brute forcing a lot.
After the password is hashed, it is used as the key for a AES 256 GCM encryption.
The encryption is applied to a gziped tar archive. By now, this only includes a single file with no relevant content.
As soon as the encryption is finished, the result may look like this:
{
  "c": "18e2c33ccfa4817b4fd8b27131bdb9fb8aaccd12051655ba7e3481b1df7d6d8ce17ec1c09abfac0f4655b5cedba8ca04cada1e6f505d3d25586ebeb92120842780c0169ece821ef439f8905e2...",
  "i": "fbabce2b28474067b08a75af06d1bced75e770c16c0e3ff787562b26d40e41da2240cda46276a6f7ae8ff47396cbed945573e7d960869bb957b8345316e3499602b0b1d83f71dd992de66c7a4bcb627041df078340638c12f9355499d2d3d48a",
  "t": "e4f6ba670160923d7f8aa6543ad95ab1",
  "s": "c661f93d7e09d68f3195c910e98a94c452e22156c491c0b2c8eeedd7898b6e59"
}

There is only one big problem with this. The file is way to big for a tar archive with a 4 letter string inside.
So, lets explore the content of this file.
We can see four different parts in this JSON: c, i, t and s.
c Ciphertext
i Initialization Vector
t Tag
s Salt
The ciphertext contains the actual encrypted data. It may vary in size a lot.
The IV is used for AES encryption and stays around 96 bits.
The tag is used to check if the decrypted data can be authenticated. It should not vary in size a lot.
Lastly, the salt is used to hash the key one last time, thus making the vault resistant against rainbow tables.

The problem with all of this is, that the data is stored in hexadecimal 🤦. Yes, binary data is converted into hex, so I can store it in my JSON.
This means, that the next thing I will have to do is to use a Buffer instead of JSON.

6/16/24

Part 1

After I replaced the JSON with a Buffer and am not storing binary as hex data anymore, the encrypted data is now half as big.
The next part of Vault is adding support for uploading and downloading files.

Part 2

I added a basic file overview. This sounds easier than it actually is.
There were some problems with the FE (it has to be easy to use...) and the BE.
On the back-end side I encountered some problems with listing the files in the terminal.
Next thing is to add support for uploading files and viewing the files.
The encrypted file looks like that now btw.:

			*0],@6VPMK/eto^=RˈvB    Rhg#N_ZplV{6}dm9UUg4$MdL'Q}d9B?0> mM"X¥=7=;
                                                                   6H`g(?DԚw.y貚TjJ_w=rPX5MAYky
ǧC旜O2{Aj0;dz}I7[]nWIcy[j}"bZ1x"@v
			

🤓👆I resampled the CSS class I use for file manager for the vault file manager.

6/17/24

The code for downloading a file is done. It works like this:
  1. User requests a file
  2. Vault is decrypted
  3. File is extracted from the archive to a temp folder
  4. Vault is encrypted again
  5. Temp file is stored in a variable
  6. Temp file get overwritten 3 times with random data
  7. Data is sent to the frontend and downloaded from there
There belongs a "The" in front of all of these points, I know.
Now, that the FE has a nice loader and smooth animations, I will continue with adding support for uploading files.
If anyone wonders, this is the code I use to send the data to the frontend and download it:
res.writeHead(200, {
  "Content-Type": "application/binary",
  "Content-disposition": "attachment;filename=" + path.basename(fpath),
  "Content-Length": data.length,
});
res.end(Buffer.from(data, "binary"));

6/19/24

Today, I added support for uploading files to Vault. It took me way too long to figure out how to do proper file uploads to Express.
In the end, I settled with using multipart/form-data and multiparty for handling the upload.
On the way to the upload, I also fixed some bugs like race conditions and made sure that the vault would be safely created, locked, and unlocked.
This part is handled using some try catch tags.

The upload works like this:
  1. The user opens the vault and the key gets stored into the sessionStorage on the client side for further use.
  2. The upload picker is selected and a file is opened.
  3. The file gets put into a FormData object together with the cached key and some information.
  4. The server parses the file and copies it to a second tmp location.
  5. The file is added to the vault.
  6. Every temp file is deleted and overwritten 3 times.
Some other "happy little undocumented features" aka bugs I encountered were checking that a file does not have the same name as a file that is already in the vault.
Sadly, I had to stop compressing the files for now because you can't add files to a compressed tar file.
This means that the next thing on the list is adding support for renaming, deleting, and compressing the file.

In the few days I did not work on this, I was fixing some security and DoS bugs.
Please star the project here: Repo

6/20/24

Today, I wrote file deletion support for Zentrox Vault.
This works by unpacking the vault, removing the file, and packing it again.
In addition to that, I started working on the backup feature for Zentrox.
In my opinion, Vault is nice for protecting your data from being stolen, but not from being overwritten or broken.
Therefore, I am planning, but cannot promise, that I will implement Google Drive connection.
To connect with Drive, I am trying to use Google Drive API.

The next thing on the agenda is adding folders and finishing the backup.
I also changed the frontend a bit and started cleaning up the code.

6/24/24

I worked on the Vault's virtual file system (aka v²fs) the last few days.
It allows the user to create files and folders and delete files.
The system is built around a tar archive with compressed files and AES encryption.
The user can unlock it and from there manage their files.
The backup feature announced on 6/20/24 is currently just a button that lets you download
the entire vault as an encrypted blob. This is far from the experience I want to create, but
for now I want to take a small break from Vault and v²fs for the next few days.

I also have started the development of a client for Vault that is written in Go.
Why another project? I have started this project because I really want to learn something more than
just the next cool JS loop feature.
In addition to the Go-based client, I also started something else: Infothing.
I do not think that I will release this; it is just a small project that lets you view information
about put cool information here. It is mainly for learning React since I actually have avoided
big frameworks like React, Vue, or Angular until now.
In the next few days, I am looking forward to trying something new like the SMB implementation for Zentrox
or extending the file manager.
Feel free to vote here about what I do next.
Can't promise I can/will actually do this, though.