I am looking at a way to do client-side cryptography in Javascript (keeping http://www.matasano.com/articles/javascript-cryptography/ in mind) and have found SJCL. But I seem unable to find good code examples for it. Any pointers?
2 Answers
I did a presentation last year titled Developer's Guide to JavaScript and Web Cryptography and have the demo site online at https://jswebcrypto.azurewebsites.net/
This includes simple Hash, HMAC, PBKDF2 and AES examples for OpenSSL command line (as a baseline) SJCL, CryptoJS, Node.js Crypto, and even W3C Web Cryptography API
Here are the SJCL examples:
Hash
var out = sjcl.hash.sha1.hash("The quick brown fox jumps over the lazy dog");
var hash = sjcl.codec.hex.fromBits(out)
// "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"
HMAC
var key = sjcl.codec.utf8String.toBits("key");
var out = (new sjcl.misc.hmac(key, sjcl.hash.sha256)).mac("The quick brown fox jumps over the lazy dog");
var hmac = sjcl.codec.hex.fromBits(out)
// "f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8"
PBKDF2
var hmacSHA1 = function (key) {
var hasher = new sjcl.misc.hmac( key, sjcl.hash.sha1 );
this.encrypt = function () {
return hasher.encrypt.apply( hasher, arguments );
};
};
var passwordSalt = sjcl.codec.hex.toBits( "cf7488cd1e48e84990f51b3f121e161318ba2098aa6c993ded1012c955d5a3e8" );
var derivedKey = sjcl.misc.pbkdf2( "password", passwordSalt, 100, 256, hmacSHA1 );
var hexKey = sjcl.codec.hex.fromBits( derivedKey );
// c12b2e03a08f3f0d23f3c4429c248c275a728814053a093835e803bc8e695b4e
Note: This requires you in include sha1.js in addition to sjcl.js.

- 41,386
- 23
- 126
- 155
-
That website with examples is really useful, thanks! Also, if you leave out the hmacSHA1 function and not pass it in as an argument, it will by default use hmac SHA256. – janka102 Jul 02 '14 at 22:02
-
2@kevin-hakanson While reading your answer I've noticed, that in `PBKDF2` example function `hmacSHA1` does nothing - the same key is returned both with and without it - http://jsfiddle.net/2802m8n5/. Can you please tell why is it happening? – eawer Sep 11 '14 at 18:07
-
Updated Fiddle (http://jsfiddle.net/2802m8n5/1/) to include sha1 (not part of sjcl.js) https://github.com/bitwiseshiftleft/sjcl/blob/master/core/sha1.js – Kevin Hakanson Sep 13 '14 at 15:42
-
https://github.com/vibornoff/asmcrypto.js is x4 faster for PBKDF2 – David Dec 28 '15 at 13:11
-
@KevinHakanson I'm trying to implement your PBKDF2 example, but the sha1 functions need access to sjcl functions. How do you share the namespace between them? http://stackoverflow.com/q/41044652/4490400 – Atte Juvonen Dec 08 '16 at 17:00
This might be a bit late, but I too have recently been looking into how to do client-side cryptographic hashing, and the answer by Kevin Hakanson was very helpful, the demo site is very useful too! It shows how to use a custom PseudoRandom Function with PBKDF2 (the HMAC and SHA1), but I figured out that if one is not passed in, SJCL has defaults and I just wanted to show how to do that, along with generating a random salt.
I also found the sjcl docs quite helpful.
To generate a random salt and use PBKDF2 on the password "password", you could do this, which ends up being just 3 lines:
// Each random "word" is 4 bytes, so 8 would be 32 bytes
var saltBits = sjcl.random.randomWords(8);
// eg. [588300265, -1755622410, -533744668, 1408647727, -876578935, 12500664, 179736681, 1321878387]
// I left out the 5th argument, which defaults to HMAC which in turn defaults to use SHA256
var derivedKey = sjcl.misc.pbkdf2("password", saltBits, 1000, 256);
// eg. [-605875851, 757263041, -993332615, 465335420, 1306210159, -1270931768, -1185781663, -477369628]
// Storing the key is probably easier encoded and not as a bitArray
// I choose base64 just because the output is shorter, but you could use sjcl.codec.hex.fromBits
var key = sjcl.codec.base64.fromBits(derivedKey);
// eg. "2+MRdS0i6sHEyvJ5G7x0fE3bL2+0Px7IuVJoYeOL6uQ="
If you wanted to store the salt, you probably want to encode it
var salt = sjcl.codec.base64.fromBits(saltBits);
// eg. "IxC/6ZdbU/bgL7PkU/ZCL8vAd4kAvr64CraQaU7KQ3M="
// Again I just used base64 because it's shorter, but you could use hex
// And to get the bitArray back, you would do the exact opposite
var saltBits = sjcl.codec.base64.toBits(salt);