Horizon introduced server side encryption, a new feature that secures files at rest with a randomly generated password during upload.
This article talks about this feature in depth, such as the technical aspects of our implementation, comparison with similar Horizon features and some of its limitations.
Encryption is a way of scrambling data so that only authorized parties can understand the information. In technical terms, it is the process of converting human-readable plaintext to incomprehensible text, also known as ciphertext. In simpler terms, encryption takes readable data and alters it so that it appears random. Encryption requires the use of a cryptographic key: a set of mathematical values that both the sender and the recipient of an encrypted message agree on.
Encryption gives users more peace of mind when it comes to the security and privacy of their files.
Server side encryption means that files are uploaded to the server in plaintext first, then the server does encryption. The cryptography happens in the background.
Server side encryption requires trust in the server. Since encryption is not done client-side, users must trust that the server is properly encrypting their files and discarding the key to prevent unauthorized decryption at a later date. This cannot be verified, unlike with client-side encryption, as encryption and decryption happens in the background (on the server) and seamlessly.
Alice wants to upload a file and encrypt it at rest.
She uploads her file unencrypted to the server, the server encrypts the file with a key, and the server stores the file encrypted.
If implemented in a privacy-preserving manner, the server discards the key and only keeps the necessary data, such as the encrypted form of the file.
Enabling server side encryption is easy, and only takes one click.
By default, enabling server side encryption will override your current shield level (if you have one) and use Level 2, as it is our recommended shield level. You may change the shield level to 1 or 3 if you choose.
Shield levels are a way to visualize the speed impacts server side encryption may incur.
There are 3 shields: Level 1, Level 2 and Level 3.
The higher the level, the more speed you sacrifice for security and privacy.
Level 1 provides the most basic protection. All files are encrypted using AES-256 without any integrity verification. While this provides the most speed, it may be easier for attackers to tamper with the encrypted data.
Level 2 is significantly more secure than level 1. All files are encrypted using AES-256 and stored with a SHA-256 HMAC signature to verify file integrity. This prevents encrypted file tampering but may slow down uploading and decryption.
Level 3 is similar to level 2, but uses SHA-512 for HMAC signature computation instead of SHA-256. This level may heavily slow down uploading and decryption, especially for larger files.
When users enable server side encryption, files are uploaded to the server in their plaintext format.
Upon receiving the plaintext file, the server generates a random 32 byte password. This password is used to stream encrypt the plaintext file. Once stream encrypted, the encrypted file is stored on the server while the original plaintext file is permanently discarded.
The key is sent to the user. It is also hashed server-side with Argon2id and stored in the database.
Since the password is hashed, the hash can only be used to verify that the provided password for decryption is correct, not to decrypt the encrypted file.
Optionally, if the user set their shield level to one that requires integrity verification, the server generates an HMAC signature with the respective hashing algorithm and stores it in the database.
At this point, the server only has the encrypted file and encryption metadata required for later decryption, but NOT the password. The server or other administrators cannot decrypt the file without the correct password, which is not stored in plaintext.
Horizon's server side encryption implementation uses AES-256 bit encryption in counter (CTR) mode for stream encryption and decryption.
Prior to encryption:
The plaintext password is added to the HMAC hash.
A hash is a representation of a piece of data and cannot be reversed. We cannot get the plaintext password from the hash after computation.
The plaintext file is read in 4 Kb chunks. Each chunk is individually encrypted using AES-256-CTR and added to the HMAC hash.
Once the entire file has been encrypted and HMAC hashed, the IV is added to the HMAC hash.
The HMAC hash is converted into a hex form.
The encrypted file is written to disk, while the IV and HMAC hashes are stored in the database.
The plaintext password and IV are added to the HMAC hash along-side the actual file chunks to further prevent encrypted data tampering.
On decryption, the provided password is matched against the Argon2id hash stored in the database.
If it is incorrect, the server aborts decryption. If it is correct, the server attempts to decrypt the encrypted file.
A SHA-256 or SHA-512 hash is initialized for HMAC signature verification with the plaintext password.
The server reads the encrypted file in 4 Kb chunks and decrypts each chunk. Each chunk is added to the HMAC hash.
Once the chunks have been decrypted and added to the HMAC hash, the IV is then added to the HMAC hash.
If the stored HMAC hash does not match the newly computed HMAC hash, the server refuses to decrypt the encrypted file.
To put it simply, server side encryption requires trust in the server, while Horizon Vault is essentially trustless. You can view your browser network activity when using Vault to check that Horizon is not sending your decryption password anywhere.
While Horizon Vault overall has better security due to its mostly trustless system, server side encryption can still be useful to those who trust Horizon to not be malicious actor and implement encryption well.
The following is a simple table to demonstrate the strengths and weaknesses of server side encryption.
|Feature||Server side encryption||Horizon Vault|
|Encrypts files with a version of AES-256||Yes||Yes|
|Requires trust in the server||Yes||No|
|Uses stream encryption and decryption||Yes||No|
|Works with third party upload clients, like ShareX and Sharenix||Yes||No|
|Fast||Yes, server does encryption||Can be, depending on user hardware|
It depends on your comfort level. If you trust Horizon enough to implement server side encryption well and not log keys in plaintext, then sure, by all means go for it. However, if you need more peace of mind that nobody, except for you, can ever decrypt your files, even if the server is compromised, then you should probably be using Horizon Vault.
Using Horizon Vault obviously comes with its trade-offs, but it should be the primary option for extremely sensitive documents.