For the moment, encryption (if activated) is done on server's side. It would be nicer to have it on client's side:
- More secure for client
- Less CPU usage on server
Now, when you use encryption, you have to wait after upload has finished that server encrypts the file. If client's side encryption cuts that time off, it would be so great! Or at least we need some progress bar to show encryption time.
Sure, server side encryption is really a pain for CPU resources. I will see how to do this soon :)
The only thing to pay attention to is that the user have to choose to encrypt or not.
If client's side encryption is always enabled, users won't be able to embed uploaded files or to download them directly (as they will need some js client to do the job).
An other detail that would be interesting is to also encrypt the file name by the client for more privacy.
No ETA at the moment, but here are some plans. Comments are welcome.
We could use asmcrypto in order to have AES (in CBC mode), hashing (SHA) and RSA.
Notes: This method should:
- avoid anyone who does not have the public key provided with the link to decrypt file
- avoid anyone who does have the public key to alter file's content
To send an encrypted file
- Start a new async upload with the server
- Generate an asymmetric key pair (PUK/PRK), a symmetric key (k) and an Initialization Vector (IV)
- Upload a chunk to the server containing 2 bytes of version (0)
- Upload a chunk to the server containing PRK(k)
- Upload a chunk to the server containing the IV (can be public)
- Upload a chunk to the server containing random data (size of encryption block)
- Upload a chunk to the server containing the file size in bytes (uint64) encrypted with k
- Upload a chunk to the server containing the file's name (padded with spaces), encrypted with k
- For each data block of the file: feed HASH_1 with clear data, encrypt block and send block to server
- Last block is padded with random data
- Upload a chunk to the server containing PRK(HASH_1)
- Finalize async upload with server, give a random name.
- Show the user a link containing link code as usual + PUK key
To get an encrypted file
- Get link code + PUB key from the link
- Download the first 2 byte from the file and check if client is able to decrypt this version, abort otherwise
- Download PRK(k) and decrypt k using PUB key
- Download IV and initialize decryption
- Download and decrypt with k the first (random) block, then trash it
- Download and decrypt with k file size in bytes
- Download and decrypt with k file's name, strip name to remove spaces
- Download each block of data using file size
- For each downloaded block: decrypt with k, feed HASH_2 with clear data and concatenate clear data to a single file
- Strip file to remove padding using file size
- Download PRK(HASH_1) and decrypt with PUB to get HASH_1
- If HASH_1 == HASH_2, file integrity is OK, abort otherwise
- Make the user download the clear file from it's local browser storage using file's name