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.
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.
// 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.