jsCrypto
Fast symmetric cryptography in Javascript

Emily Stark     Mike Hamburg     Dan Boneh
estark, mhamburg, dabo at cs dot stanford dot edu



Introduction

Why use cryptography in Javascript? One major reason is the need to encrypt data before uploading it to a server; this is useful where the server needs to store data but doesn't wish to see it in the clear. It can also be used in desktop applications written in Javascript - for example, Firefox extensions.

We offer a fast, small symmetric encryption library written in Javascript. Though several such libraries exist, jsCrypto offers several advantages.

Subscribe to the jsCrypto mailing list to receive email updates when changes and bug fixes are posted:

Email: Unsubscribe:

Whitepaper

The following paper contains detailed information about the implementation and running times.

Symmetric Cryptography in Javascript
by Emily Stark, Michael Hamburg, and Dan Boneh
To appear in ACSAC 2009. (bibtex)


Performance

jsCrypto is at least 340% faster than previous Javascript implementations of AES in all browsers. In Internet Explorer, it is over 1000% faster. The performance graphs below show encryption speed (kB/second) compared to various other implementations.*



Usage

Include the following in the <head> section, and place the contents of the js folder in the same directory as your HTML file:

<script src="jscrypto.js" type="text/javascript></script>

Now add an event listener specifying a function to call when the random number generator is seeded. In this example, our callback function is called encrypt:

Random.addEventListener("seeded", encrypt);

Once the random number generator is ready to produce random numbers, the encrypt function will be called. An example of what an encrypt function might look like:

function encrypt() {
  var salt = [];
  // Populate the salt variable with data from the server (see note below)

  // The key is an array of 16 bytes, which can be generated from a user password:
  var key = generateKey(document.getElementById('password').value, salt);
 
  var cipher = new aes(key, CCM);
  var iv = Random.random_words(4);
 
  var plaintext = document.getElementById('formFieldToEncrypt').value;
  var ciphertext = [], tag = [];
  var adata = "";
 
  cipher.encrypt(iv, plaintext, ciphertext, adata, tag);
 
  // Send ciphertext and tag to server here
}

If you are using user passwords to generate encryption keys (with the generateKey function), then you will need to assign each user a salt, which is eight random bytes, and store the salt associated with each user on the server. This salt can be generated on the server when each user is registered. Retrieve the salt from the server for key generation from a user's password.

The second line of code generates a 16-byte key from a password entered by the user on the form. The third line initializes an AES cipher object in CCM mode; you can alternatively specify OCB mode with var cipher = new aes(key, OCB);

The fourth line retrieves some data to encrypt from a form field. Next, we initialize arrays that will hold the ciphertext and MAC tag after cipher.encrypt() is called. You can also specify associated data to send all with the encryption; the associated data (adata) will be MAC'ed but not encrypted.

Finally, we call cipher.encrypt() to encrypt and sign the data; the resulting ciphertext and tag are stored in the respective variables.

To decrypt a ciphertext with an associated MAC tag (where ciphetext and tag are arrays of bytes, and adata is a string of data that was authenticated but not encrypted with the plaintext):

function decrypt(ciphertext, adata, tag) {
  var key = generateKey(document.getElementById('password').value);
  var cipher = new aes(key, CCM);
  var plaintext = cipher.decrypt(ciphertext, adata, tag);
  if (plaintext != "") {
   // Display plaintext here
  } else {
   // Data failed to authenticate
  } }

As in the encryption function, we derive a 16-byte key from a password entered by the user and then initialize a cipher object. If the tag is a valid signature for ciphertext and plaintext, then cipher.decrypt returns the decrypted ciphertext. Otherwise, cipher.decrypt returns an empty string.


Download

The following zip archive includes the crypto library (in the js directory, as well as two sample applications (in the samples directory). One of the sample applications encrypts the value of a cookie, and the other encrypts values entered by the user in a form.

Download jsCrypto
(Last modified: 02/22/10)

View sample application 1
View sample application 2

Changelog


* The implementations we compared to: