I would like to encrypt user data in JavaScript in a browser before it gets sent out for storing. I read that this is generally a bad idea but considering the following points at least most of the arguments should be dismissed:

  1. The website is delivered via IPFS. Therefore all its contents can be trusted, nobody can inject malicious code or modify it.
  2. The website is running in a browser in a sandbox environment without extensions, e.g. chrome with incognito mode and all extensions disabled.
  3. The data is sent to IPFS (which is also used for retrieving it later) so nobody can inject or modify it.
  4. For encryption SJCL "the only example of a trustworthy crypto library written in Javascript" is used.

Does this finally allow us to use easy JavaScript encryption or are any remaining attack vectors that I do not see?

  • 1
    SJCL etc.: Did you ever meet a crypto lib author saying his own lib is not good? Right. The libs are as good as the authors, but latter factor varies. IPFS...Therefore all its contents can be trusted, nobody can inject malicious code or modify it. Lol? ... Any reason you want to make your own thing instead of using established stuff?
    – deviantfan
    Dec 1, 2015 at 11:57
  • 1
    I never met a crypto lib author. The quote about the trustworthiness of the library is to the best of my knowledge not from the authors of the library but from reference 1. Sorry if my question insults you, but I'm far from being an information security expert. Therefore I'm not making my own stuff, I was just thinking of using IPFS + a library (that I both don't have ties with). What would be "using established stuff" in the framework of my question (JavaScript encryption in a browser)?
    – SCBuergel
    Dec 1, 2015 at 12:28
  • It depends on how you want to encrypt the data. There is openpgp.js for example.
    – user6090
    Dec 1, 2015 at 13:10
  • Doesn't this question essentially reduce to "which JS crypto library do you recommend"?
    – Anko
    Dec 1, 2015 at 15:36
  • @Sebastian I'm not insulted (?) The established solution is still not to use JS encryption at all. If IPFS doesn't provide what necessary, I'd go back to the usual HTTP+TLS etc.
    – deviantfan
    Dec 1, 2015 at 16:20

3 Answers 3


Well, one issue until very recently (i.e. last week!) was that implementations of Math.random() in most browsers were, frankly, rubbish. Both V8 (the Javascript engine behind both Chrome and NodeJS) and Spidermonkey (the Firefox engine) used PRNGs with too short periods, and there is evidence to suggest that IE and Edge also have broken PRNGs. This means that if there are any calls to them from anything in a layer that relies on them, there is going to be a limited set of possible results. Now, this can still be a lot of results (about 590 million, for the V8 case), but that is a lot less than the ideal 2^132 (5,444,517,870,735,015,415,413,993,718,908,291,383,296).

This means that any attack has a much higher chance of success - intercept data in transit, and then attack offline. Might take a while, but AES is fast on modern processors, and computers are cheap.

Other issues with this could be: how can you ensure that there are no extensions in use? The browser is out of your control. How can you be sure that there aren't undiscovered flaws in IPFS? Security professionals tend to prefer systems that have been subject to a lot of attacks, and not broken, to new systems that haven't been tested as much. Even if the mathematical theory is perfectly sound, is the implementation correct? One typo or incorrect addition could result in a massive problem - see Heartbleed.

There are also problems with other parts of the browser infrastructure that can affect some types of in-browser crypto. The FileWriter interface was deprecated, meaning that anything larger than the browser memory can't be reliably decrypted (there is no sensible way to write it to disk - oddly enough, FileReader works fine for encryption). Browser support for encryption operations is lacking - Windows and Linux can use native calls for AES nowadays, on modern processors, but it would take work to make browsers able to do the same.

We're getting there, but it's not yet a solved problem. If IPFS stands up to scrutiny, the browser manufacturers implement improved randomisation sources, and so on, it'll be close. The extension problem doesn't seem likely to go away though - people seem attached to their adblockers, and probably don't want to trade security through not having any extensions turned on for adverts!

  • don't want to trade security through not having any extensions turned on for adverts ...especially because ad networks are good malware distributors, yes.
    – deviantfan
    Dec 1, 2015 at 18:12

There are many pitfalls, when doing crypto in JavaScript. I recommend looking into the WebCrypto API, as it provides cryptographic primitives that enable you to use modern encryption.

I recommend looking at Tim Taubert's presentation about the WebCrypto API as it walks you through a notes app that stores its content encrypted. In it's ending, it recommends deriving an encryption key via PBKDF2 and encrypts using AES-GCM.

Your remaining problems are likely:

  • Denial of Service: Can you trust the storage provider not to remove data or parts of the data?
  • Performance: If all user data is one big encrypted blog, you'll have to re-encrypt everything even on minimal changes.

You could counter the performance problem by encrypting items in an array selectively, but this will bring additional security considerations: You need to avoid nonce re-use and store nonces per-item. An untrusted storage provider may still delete rows, unless you build up a hash tree to deeply verify data integrity.

You could also allow password changes with a "key encryption key" (i.e. generate random storage-key for encryption, encrypt this storage-key with the password-derived "key encryption key").

As you see, cryptography in itself is not a panacea. You have to come up with a great deal of solid cryptography engineering on top.

  • There's no denial of service in IPFS. Either the data is found and can be sent, or it isn't sent. A malicious IPFS node could send the wrong data for the correct hash, but the client will verify that and discard the wrong data.
    – fiatjaf
    Jan 4, 2018 at 21:43

Don't do this. IPFS isn't secure. Someone between your user and the IPFS node might decide to intercept and change queries. There's also the issue that someone might change your files locally in IPFS. Anyone who gets their files from that host will receive malicious code. Someone could write a virus that changes the content of your files as they arrive on your users' computer.

Even if we assume that IPFS is perfectly secure, cross-site scripting is a real issue. It's been done in various ways, and all an attacker needs to do to get through your encryption is change a function you rely on.

All an XSS attacker needs to do is get a single line of code to run:

Math.random = function () {return 0.4;};

and your whole encryption probably falls without anyone ever noticing. Worse, your user data will be stored insecurely on IPFS, open for anyone who knows your functions (anyone with access to IPFS) and the random seed 0.4 to read.

There are tons of other ways to break your encryption if you do it in browsers. For more, check the page you linked - you can exclude very few of the points made there. If you don't understand why they are still valid, you should spend some time reading up on networking/cryptography.

If you want to build a distributed system in IPFS that has encrypted data, have a centralized authentication server to back it up, and use that server for everything you need in terms of cryptography.

  • How can be someone between your user and the IPFS node? The user is the IPFS node.
    – fiatjaf
    Jan 4, 2018 at 21:44

You must log in to answer this question.

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