An open API service indexing awesome lists of open source software.

https://github.com/sitegui/pbkdf-sha256-asm

SHA256, HMAC-SHA256 and PBKDF-SHA256 in JavaScript asm.js
https://github.com/sitegui/pbkdf-sha256-asm

Last synced: over 1 year ago
JSON representation

SHA256, HMAC-SHA256 and PBKDF-SHA256 in JavaScript asm.js

Awesome Lists containing this project

README

          

# PBKDF-SHA256 in asm.js

My first attempt to compile C to JavaScript :)

This is my own implementation of three related crypto algorithms:

* SHA-256, based on [FIPS 180-4](http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf)
* HMAC with H=SHA256, based on [FIPS 198-1](http://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf)
* PBKDFv2 with H=SHA256, based on [NIST SP800-132](http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf)

**NOTE**: this is a toy project and should not be taken too serious, i.e. don't use this implementation in critical production code. There are much more robust crypto libs out there!

## Benchmark
A small benchmark comparing this implementation to [CryptoJS](https://code.google.com/p/crypto-js/), a crypto lib written directly in JS.

The time that it took to execute 5000 rounds of PBKDF over input `message='password', salt='salt'` was measured and is represented in the graph bellow in rounds per second. That is, what should be the value of the rounds parameter if one want the function to return in 1 second.

![Graph](https://raw.githubusercontent.com/sitegui/pbkdf-sha256-asm/master/asm.png)

Ok, I may be comparing apples to oranges, since CryptoJS is a much broader lib and is not limited to only SHA256. But even though, the result is pretty clear: JS almost as fast as C!

Just for the record, this was my CryptoJS bench code:
```javascript
var pbkdf = CryptoJS.algo.PBKDF2.create({
keySize: 256 / 32,
hasher: CryptoJS.algo.SHA256,
iterations: 5000
}),
password = CryptoJS.enc.Utf8.parse('password'),
salt = CryptoJS.enc.Utf8.parse('salt'),
then = Date.now(),
key = pbkdf.compute(password, salt).toString(),
now = Date.now(),
dt = now - then
if (key === '8fc2bcffbb4b1ac9b9de03588d390f3d9bf336c2c4422c90c158cc714225f629') {
console.log('Took ' + dt + ' ms, ' + Math.round(5e6 / dt) + ' rounds/s')
}
```

## Using
Include the file `js/pbkdf_min.js` and bind the functions with:
```
var sha = Module.cwrap('sha_simple', 'string', ['string'])
var hmac = Module.cwrap('hmac_simple', 'string', ['string', 'string'])
var pbkdf = Module.cwrap('pbkdf_simple', 'string', ['string', 'string', 'number', 'number'])
```

This will set three functions. All them return a 64-char hex-encoded string and receive UTF8 strings:

* sha(message: string) -> string
* hmac(key: string, message: string) -> string
* pbkdf(password: string, salt: string, blockIndex: int, rounds: int) -> string

Using is simple as `alert(sha('my-great-message'))`

[See a simple example](http://sitegui.github.io/pbkdf-sha256-asm)

### Hex input
Each one of the 3 functions have another version that takes a hex-string (like `'fa40fa'`) as input:
```
var shaHex = Module.cwrap('sha_simple_hex', 'string', ['string'])
var hmacHex = Module.cwrap('hmac_simple_hex', 'string', ['string', 'string'])
var pbkdfHex = Module.cwrap('pbkdf_simple_hex', 'string', ['string', 'string', 'number', 'number'])
```

## Compiling
First you need to install [emscripten](https://github.com/kripken/emscripten/wiki). When done, just run one of the commands bellow in the repository path:

### SHA256
emcc c/sha.c c/util.c c/memory.c -o js/sha.js
emcc c/sha.c c/util.c c/memory.c -DNDEBUG -O2 --memory-init-file 0 -o js/sha_min.js

### HMAC-SHA256
These already include SHA256

emcc c/hmac.c c/sha.c c/util.c c/memory.c -o js/hmac.js
emcc c/hmac.c c/sha.c c/util.c c/memory.c -DNDEBUG -O2 --memory-init-file 0 -o js/hmac_min.js

### PBKDF2-SHA256
These already include both HMAC and SHA256

emcc c/pbkdf.c c/hmac.c c/sha.c c/util.c c/memory.c -o js/pbkdf.js
emcc c/pbkdf.c c/hmac.c c/sha.c c/util.c c/memory.c -DNDEBUG -O2 --memory-init-file 0 -o js/pbkdf_min.js

### Tests
emcc c/main.c c/test/hmac.c c/test/pbkdf.c c/test/sha.c c/test/util.c c/pbkdf.c c/hmac.c c/sha.c c/util.c c/memory.c -o js/test/test.html
emcc c/main.c c/test/hmac.c c/test/pbkdf.c c/test/sha.c c/test/util.c c/pbkdf.c c/hmac.c c/sha.c c/util.c c/memory.c -DNDEBUG -O2 --memory-init-file 0 -o js/test/test_min.html
And then just open the .html page. It should log some 'OK!' messages in the console and also the benchmark result.
The `NDEBUG` flag turns off memory checks that I've used to make sure all allocated memory was freed correctly.