There are lots of older articles1 on why in-browser crypto is a bad idea. Most are summed up via: http://bitwiseshiftleft.github.io/sjcl/

We believe that SJCL provides the best security which is practically available in Javascript. (Unforunately[sic], this is not as great as in desktop applications because it is not feasible to completely protect against code injection, malicious servers and side-channel attacks.)

It seems the biggest problem they mention is that an attacker could serve you bad javascript that the browser executes because XSS is so common.

Between TLS and an extremely restrictive Content Security Policy, is this still an issue and therefore in-browser crypto a bad idea?

The goal of the encryption is not to replace TLS. It is being used to encrypt documents before they reach the server so only the sender and recipient can read them.


  • It is and always will be a bad idea because you need TLS to ensure that the browser crypto js is authentic. And if you have TLS you don't need js crypto Aug 8, 2016 at 17:46
  • I clarified the question. The encryption I want is not to replace TLS. It's for encrypting the content so it cannot be read by the server.
    – erik
    Aug 8, 2016 at 17:56
  • It is still a bad idea because the server admin can always change the js crypto lib and read the "client encrypted" info on the server. You need to use an open source client-installed program, which is not under control of the server admin Aug 8, 2016 at 18:10
  • 1
    @NeilMcGuigan: generally server admins can do whatever they want to ruin security, but if the keys aren't stored on the server, how can said admin read client-encrypted data? (prompting+PBKDF, indexedDB, crypto.subtle, etc)
    – dandavis
    Aug 8, 2016 at 19:03
  • 2
    It's how LastPass does it. At the end of the day the user has to trust that the client executed script hasn't been modified. Aug 9, 2016 at 13:01

1 Answer 1


I've been hoping someone would ask about this topic, i've been doing a lot of research in the area.

You are correct that most of the points in javascript-cryptography-considered-harmful are outmoded by newer browsers. Aside from the obvious issue of someone compromising the server, which is a separate issue and presents a problem to TLS as well, the main points are now "fixed":

  • window.crypto.getRandomValues() uses a real CSPRNG
  • HTTPS is common and much cheaper now than in 2011
  • CSP's integrity and nonce <script> attributes can secure script delivery to make sure what's running is expected
  • SJCL is years more mature than in 2011, and no major issues are outstanding
  • malleable runtimes don't matter if you don't have XSS, which CSPs are now good at stopping

Furthermore, we now know that HTTPS is not an absolute guarantee of privacy (snowden/heartbleed/crime/breach/etc), but proper end-to-end encryption is. We can also now implement fairly robust, battle-tested, and secure libraries, backed by a more secure JS runtime than what was offered in 2011; "use strict" widely supported, a CSPRNG, binary structures, web workers with sealed runtime environments etc.

Those are updates to the main points, but if you have concerns about other aspects of client-cryptography, i'll be happy to address them.

Of course, nothing is perfect:

  • really old browsers still have issues or can't run new code securely
  • user-added extensions can run whatever code they want
  • malware can replace the whole browser with something sinister, or steal data pre-encryption
  • phishing can trick the user into using something besides your safe site.

In short, i think post-snowden, we should try to keep plain private data off servers wherever we can help it, and solid end-to-end encryption, done right, greatly enhances the privacy of your users and the security of their content.

  • This answer addresses most of the problems outlined in the articles referenced in the question. However, the problem that still remains (as of 2020) is the 'chicken and egg' problem with browser crypto - i.e. If you can't trust the server with your secrets, then how can you trust the server to serve you secure js crypto code?
    – mti2935
    Mar 15, 2020 at 21:07
  • @mti2935: we're getting out of scope, but I can think of at least 3 ways: The integrity attribute could match known libs, we can trust the certs, and ultimately we can view the actual code that runs; especially as window.crypto does more than generate randomness like in 2016, it uses real crypto, so we don't have to trust a server or big code libs, just browsers. We can what-if all the way to the matrix, and none of these 3 are 100%, but issues of server trust are well-covered by other answers.
    – dandavis
    Mar 16, 2020 at 2:38
  • Consider a case where the server administrator 'goes rogue', and inserts code in the root HTML document to capture the user's private key, and send it back to the server. All of the integrity attributes would still match, and the SSL certificate would still be valid. Yes, a very thorough user could inspect the source and see the malicious code that was added, but this is beyond the scope for most users, even ones that are very technical. As of 2020, there is still not a good solution to this problem.
    – mti2935
    Jul 29, 2020 at 17:38
  • @mti2935: We can always be hurt by those we trust, but that's not what the old article was or my answer is about (technical means of protecting the browser window environment from outside attack). AFAIK, there's no way to protect any platform from bad behavior on the part of those we entrust.
    – dandavis
    Jul 29, 2020 at 17:53
  • I agree, it comes down to who the user trusts. But, in this case, the user implicitly does not trust the server, because the user is encrypting their secrets client-side, and only sending the ciphertext to the server. That is why some way for the user to verify the integrity of the client-side scripting served by the server is needed, as discussed in security.stackexchange.com/questions/238441/….
    – mti2935
    Sep 26, 2020 at 11:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .