One of the challenges we encountered in creating Opal was finding a fast and secure way to do encryption and decryption in the browser.
This post describes why browser-side cryptography has been a difficult problem, and how recent technological advances provide a solution.
For example, there are cryptography libraries that exist in both Java and Flash. These implementations are often very fast, but unfortunately they require users to install browser plugins, which many are unwilling or unable to do (for example, if they are on a public computer).
Another option is to use Chrome's Native Client, which allows browsers to run machine code compiled from C or C++. Again, such implementations can be very fast, but right now Native Client is only available on Chrome.
So while plugins and Native Client have the benefit of speed, they lack portability because they require users to install specific plugins or use a specific browser.
However, this API is still in the draft stage, and it may be a while before it sees wide adoption among the major browser vendors.
As it stands now, only
crypto.getRandomValues() has been implemented in most browsers.
Until the Web Crypto API becomes widely implemented, it's not a viable option for browser-side cryptography.
Some of the statements on that post are no longer accurate.
For example, the post makes the point that
Math.random() is not a good source of randomness, and thus it is impossible to get a suitable amount of random numbers for cryptography.
While it is true that
Math.random() is not a good source of randomness, modern browsers have a
crypto.getRandomValues() function which does provide enough randomness.
The problem then becomes which one to choose.
Currently, Firefox is the only major browser to support asm.js optimizations. This makes the encryption and decryption with js-nacl very fast in Firefox, between 2 and 8 times faster than Chrome, depending on the operation. But even in Chrome, js-nacl is blazingly fast, outperforming all the other cryptography libraries we tested.
The combination of a trusted security library like NaCl with fast performance in modern browsers makes js-nacl the obvious cryptography library for web apps like Opal.
For similar reasons, Opal uses an emscripten-compiled asm.js version of the popular scrypt library for passphrase stretching (working on the post now). You can see exact benchmarks of js-nacl and js-scrypt from the project maintainer here. We also set up some jsperf tests for js-nacl to get a better idea of performance across browser versions, feel free to run them.
Since writing this post, the V8 team has implemented many optimizations that increase asm.js performance. However, V8 still ignores the "use asm" pragma, and applies no special optimizations to the asm.js code. The issue for implementing asm.js-specific optimizations in V8 can be found here.
In our most recent testing, FireFox is still 2-4 times faster than Chrome when encrypting and decrypting with the NaCl library (both for public key and symmetric encryption), although Chrome is twice as fast at generating a key pair. A more in-depth post about these benchmarks will be published soon.