JavaScript AES and CBC implementation using ArrayBuffer
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
qunit
README.markdown
aes.js
aes_tests.js
buffer_utils.js
crypto.js
crypto_tests.js
tests.html

README.markdown

Description

This is a JavaScript AES and CBC implementation using ArrayBuffer. Why you would want that you might ask and the reason is that I wanted to do AES CBC crypto in a Chrome extension. I also wanted to make it reasonable fast (for being done in JavaScript) so the code might look a bit weird and it is also only optimized to run with Chrome v8.

Note that if you read this in a future when the WebCrypto standard is available in all browser you need to support I suggest that you use that instead.

Performance

2008 MacBook, Chrome 24, 2 GHz Core 2 Duo, 1067Mhz DDR3:
Encrypt ~12.2 MB/s, Decrypt ~8.4 MB/s

2011 MacBook Air, Chrome 24, 1.5 GHz Core i5, 1333Mhz DDR3:
Encrypt ~17.5 MB/s, Decrypt ~12.0 MB/s

If you want to benchmark yourself you can check the "CBC AES-128 Benchmark" test case in the unit tests.

Usage

// make sure both aes.js and crypto.js is included  
var iv = new Uint8Array([
  0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
  0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
]);
var key = new Uint8Array([
  0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
  0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
]);
var input = new Uint8Array(123456);

// pad input to be AES block size aligned and then encrypt  
var encrypted = Crypto.encrypt_aes_cbc(Crypto.pkcs_pad(input.buffer), key.buffer, iv.buffer);

// decrypt and then remove pad bytes
var decrypted = Crypto.pkcs_unpad(Crypto.decrypt_aes_cbc(encrypted, key.buffer, iv.buffer));

// decrypted is now a ArrayBuffer with same bytes as in input

Possible improvements and TODOs

Test if inverse equivalent cipher is faster. crypto-js AES seems to use that but haven't benchmarked their code yet.

I should write a short journal of the optimization steps and tests done to end up with the current code. The short version is: use lookup tables, don't create new objects, unroll and inline functions yourself as the v8 optimizer seem hard to predict and has some default limits that is hard to fulfill.