Benchmarking client side cryptography
Even though there are good reasons to consider javascript cryptography harmful, the long-standing choice of tools for end-to-end encryption such as GPG is not appealing to users that just do not want to choose among SERPENT or IDEA or TwoFish ciphers, therefore there are products being build to make encryption on the client side actually usable.
One of the products is Cryptelo, an end-to-end encrypted file sharing service currently under heavy development. Cryptelo leverages the advantages of clojure, especially cljx, to build for the JVM and javascript from the same codebase. This makes the task of comparing the two platforms very straightforward. Together with the Cryptelo team I tried to answer the question what performance we can expect from the client side crypto implementations on different platforms.
In particular, the platforms of interest were javascript on desktop and mobile browsers, java on desktops and native objective-C on ios devices. The algorithms tested were the cipher AES, the key derivation function PBKDF2, key derivation on elliptic curves for the Diffie-Hellman key exchange, signing and signature verification. Google's End-To-End was used for the javascript implementation and Bouncy Castle for java.
For example, we learned that on a MacBook Pro from 2011, to encrypt a file of size 7MB using AES took 3.4s in Chrome 42, 2.9s in Safari 8 and 2.6s in Firefox 38. Surprisingly, to decrypt the file, Safari needed twice the time of encrypting it! Firefox was the fastest browser for all algorithms. Implementation in JVM on the same machine managed to complete the same task in about 85ms. Ipad Air 2 from 2014 encrypted the 7MB file in 22.6s in Safari and in just 24ms in native objective-C code.
40k iterations of PBKDF2 took from 260ms to 307ms in browsers and about 58ms in JVM on the MacBook. On the Ipad Air 2 it was 650ms in the browser and 20ms in the native code.
Finally the operations on elliptic curves. Derivation of the shared secret in DH (without and with hashing) took from 51 to 71ms in the browsers on the MacBook, and around 1.3ms in JVM. Signing of SHA-256 hash (32 bytes) took from 13.6ms to 20.4ms in browsers and 1.9ms in JVM. The signature verification took from 64ms to 90ms in browsers and 1.7ms in JVM.
Ipad Air 2 did 40k iterations of PBKDF2 in 650ms in the browser and in 20ms in the native code. Deriving shared key took about 283ms in browser and 5.2ms in native code.
We also tested other mobile devices, laptops and operating systems, and different data sizes for encryption. All the results can be found in the spreadsheet.
To conclude, the performance of the standard cryptographic algorithms implemented in javascript is reasonable for files up to several megabytes on modern mobile devices and up to several tens of megabytes on laptops. Implementation in objective-C is lightning fast in comparison and compiled java on your laptop is fast enough for encrypting your entire hard drive.