I have a web app I'm hoping to write where a selection of files are zipped and encrypted in the browser before being uploaded to my server. I have a prototype of the system and it's working great. I want to do it in the browser with NO server involvement when handling the unencrypted files for privacy sake.

The general process is:

  1. The user selects local files on their computer
  2. Zip those files together
  3. Generate a key
  4. Encrypt the zip with key
  5. Upload encrypted zip to server (this is verifiably the first network usage after page load)

My goal is to know as little as possible about the uploaded package. Zipping means I don't know how many files there are and because the keys are all managed client side there is absolutely no way I should be able to decrypt the package. My service is all about storage so I never need to transmit the key anywhere. The key is available to the user for them to personally manage.

I realize that using javascript security allows my clients to manipulate values in order to cripple security but because they're only capable of modifying code that impacts them a user can only weaken the security on packages they upload. I'm assuming a user actively going out of their way to shoot themselves in the foot is not a problem I need to attempt to prevent.

MITM seems like a possibility. Eve could manipulate the requested JS files to remove encryption and an unencrypted package could be retrieved by Eve during the upload but I don't think this presents any new problem over a system where the package is sent to my server and then encrypted. HTTPS and a well educated user can help prevent a MITM from succeeding as well. "Well educated user" might be a pipe dream, but I can do my part to attempt to educate my users before the process starts.

The last and so far worst issue that's come to mind is the possibility of a malicious browser extension. It could manipulate the JS to remove encryption but the upload would still be secure using a forced HTTPS connection (the server can reject non-secure uploads). Since I read in files using Javascript's FileReader API, a malicious extension could intercept the unencrypted blob and upload it to a third party. How could I possibly defend against something like that? I know my site and servers haven't been breached but this is still a huge loss to my clients. Can anything be done about this?

If the connection with the server is 100% HTTPS enforced then what kind of attacks could target a system like this? Are there issues I haven't thought of that I need to prepare for? What can I do to ensure security as well as privacy?


What you are proposing is the same architecture that is used in online password managers like Lastpass and online Bitcoin wallets like Blockchain. You have named the two big threats: Javascript tampering and a compromised computer.

You deal with the threat of Javascript tampering by securing the server and convincing the users that your Javascript is secure.

Regarding malicious browser extensions or other malicious code on the computer, you can't do much about that. You have to leave it up to your users to ensure that their computer is secure.


Trusting the server is unavoidable, and you have to trust the server anyway if the crypto is server based. MITM attacks also apply to server based crypto, and I see no reason why a malicious plugin couldn't also attack server based crypto.

The main difference is that you're relying on the client end to do the encryption, where you have less control of the programming environment. One thing you need to be careful about is random number generation used in Javascript. Math.random() is what many people might use as a source of random numbers, but it's not appropriate for crypto use. If your're not producing enough entropy for random number generation you could easily be vulnerable to brute force attacks on the keys. See this answer for a better library to use for cryptographic purposes.

  • The crypto is not server based. I'm using a library that doesn't use Math.random(), it attempts to use window.crypto.getRandomValues() and will warn if the browser doesn't support that. As for the server, I do trust it but I'm promising my clients that there's no way I can decrypt their package and make the contents available to law enforcement. I'm eventually aiming for absolute zero knowledge. – Corey Ogburn Jun 12 '15 at 18:57
  • @CoreyOgburn I know you're not using server based crypto, but I'm comparing your approach to the server based alternative, and in that case they're equivalent. The other thing you need to be aware of is that anyone controlling the server controls the javascript. So if you're forced to put in hacks into your own code by LE, your clients could still be compromised. – Steve Sether Jun 13 '15 at 2:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.