Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Client side (javascript) file upload encryption [closed]

I'm trying to build a method for encrypting a file client side and upload it. The goal is to store the file encrypted on the server and only the end-user should be able to decrypt the file. This question has sort of been asked before, but I think I made some more progress.

My plan is to use the new Javascript File API to manipulate the file and upload it. Encryption could be done with the Stanford Javascript Crypto Library. The file should be read in chunks so it isn't completely read into memory. Every chunk is then encrypted by the crypt library. I can't figure out how to implement this. As a start I have this:

var fd = new FormData();
var file = document.getElementById('file').files[0];
fd.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/upload/");
xhr.send(fd);

Which is just a regular javascript upload. I'm trying to build a Crypt object that mimics the behavior of a File object and pass this to FormData. For every data chunk read by formdata the object should read a chunk from the file and encrypt this. I just can't figure out how FormData is processing a File object and if it possible to replicate this behavior. I'm not sure if it is the right way to do it, anybody has a suggestion?

UPDATE: Ok I'm much further now. I'm using file.slice to read the file in chunks. Then every chunk is encrypted and transformed back into a blob using a the BlobBuilder. This blob is then put into a FormData object and submitted to the server. The server will concatenate these blobs. Encrypting and decrypting one chunk with the browser is working. Now I'm working on download and decrypting multiple chunks.

There are still some problems to solve:

  • The name of the file is lost, it is not yet possible to set a FileName for a file object.
  • The encryption is still blocking (no ui update), but I think I can solve this with webworkers.
  • I can't predict the chunk size while downloading. The unencrypted chunk size is known, but for encrypted data this seems to differ. This encrypted data is stored in JSON form, I prefer not to do a string search for }. And I prefer not to store this server side.
  • Although I'm reading the file chunked, Firefox seemt to have a memory leak or read the complete file into memory. This becomes a problem for multi gigabyte files.
like image 781
Gijs Molenaar Avatar asked Oct 04 '11 10:10

Gijs Molenaar


People also ask

How do I remove encryption from a file?

Remove a password from a document Open the document and enter its password. Go to File > Info > Protect Document > Encrypt with Password. Clear the password in the Password box, and then click OK.

Is client-side encryption necessary?

Why is Client-Side Encryption Important? If you're looking for the most secure, private way to send email or transmit data, client-side encryption is your best bet. Using client-side email encryption makes it less likely for your information to be intercepted by hostile third parties on the Internet.

Why they will Encrypt the files before sending them to a client?

File encryption is a way of encoding files, including the sensitive data they contain, in order to send them securely. The encoding prevents unauthorized access and tampering by malicious actors. It keeps a file from being read by anyone except the person or people for whom it was intended.


1 Answers

Following is a solution that strongly protects files.

Pro:

  • An attacker can access the server but won't be able to use the data.
  • Even you (the developer) cannot access the data.

Cons:

  • If user loses its password, data is lost too.
  • Even you (the developer) cannot access the data (This means you cannot help the user if he encounters any problems).

If its what you need, go for it ^^. Note: all that follows happens on the Server side.

  1. use https for all transmissions
  2. When the user log in, create a hash of the user's password (e.g. sha(password + salt))
  3. Store the hash in the user's session
  4. When an upload is done, use symmetric encryption (e.g. AES) to encipher the data with the hash stored in the session as the key.
  5. When a download is done, use the same symmetric decryption method to decipher the file and send it back to the user.

This means that only a logged user can access the data as plain. And only the user to whom the data belongs. The only possibility to access the user's data is to know his password.

Note: if the user that uploads the file and the one that read the file are not the same person, you can use a combination of asymmetric and symmetric encryption instead:

  1. generate a public/private key pair for the recipient.
  2. (symmetric) encrypt the private key with the recipient's hash or a dependency of his password.
  3. When a file is uploaded, asymmetric encipher with the recipient's public key.

  4. (new) Asymmetric encryption appear to be much slower than symmetric encryption (10-100x depending on algorithms/architecture). Hence it is far better to generate a random number (the session key), asymmetric-encrypt twice (once with sender's public key, once with recipient's public key) it and store them. Then use symmetric encryption to encrypt the file (use the plain session key as the symmetric key).

  5. When the recipient wants to access the file:

    a) decipher his private key with his hash or password dependency.

    b) asymmetric decipher the file with the private key.

    b) (new) Use private key to decipher the recipient's encrypted session key. Then use symmetric decryption to decipher the file.

Hope this helps.

like image 92
Vincent Pazeller Avatar answered Sep 30 '22 07:09

Vincent Pazeller