JS is not exactly blindingly fast, that much is commonly agreed. But how slow is slow? For our password management webapp, I wrote a Qt client, which uses the QtWebKit native bridge to access a native RSA implementation (specifically, CryptoPP) and compared it to JSRSA.

Benchmarking JS engines against C++
For the test, I used Firefox 15, Opera 12.02, Chromium 21 and WebkitGTK 1.8.3 on an Intel® Xeon® X3440 (4 cores @ 2.53GHz), with Linux as OS (kernel 3.0.42). WebkitGTK (used by Midori, uzbl and others) uses the JSCore engine, which is also used by Safari, QtWebkit (in turn used by Arora and Konqueror) and other Webkit ports, so its results should be representative for most non-IE browsers.

The text to encrypt was

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui.

The text was en- and decrypted using a 512-, a 2048- and an 8192-bit key, wherever feasible the test was repeated multiple times for averaging.

Results:
(times in ms)

Engine Encrypt (512 Bit) Decrypt (512 Bit) Encrypt (2048 Bit) Decrypt (2048 Bit) Encrypt (8192 Bit) Decrypt (8192 Bit)
CryptoPP (QtWebKit bridge) 2 8 0.7 13 1.1 112
V8 (Chromium 21) 5 43 12 359 70 9000
Firefox 15 52 522 156 5166 578 74000
JSCore (WebkitGTK) 55 625 194 5356 1200 138000
Opera 18 94 29 936 102 13000

Observations:

  • Unlike other browsers, Opera executes JS in a separate thread and was still responsive, all other browsers blocked the tab (or the entire browser) completely while the benchmark was running.
  • 2048- and 8192-bit encryption in CryptoPP is constantly faster than 512-bit encryption – I assume this is due to the fact that with longer keys, the text can be encrypted in one chunk, while with 512 bit it has to be chunked, and the code I wrote for that is anything but optimized. I’ll have a look into that.

Conclusion
While Chrome and Opera are pretty fast, RSA in JavaScript is not quite ready for productive usage – at least not with key lengths >2048 bits. I am going to push the native client for our password management system, and only keep the JS version as fallback. While 2048 bit are still considered acceptable for most use cases, I’d rather have an option to switch to 4k or 8k long keys if necessary.

The code will be pushed public as soon as it is in a read- and usable state.