Browse Source

Bundle WAT using `wasm-tools` (#17)

* Bundle WAT using `wasm-tools`

* Remove compiled WASM and update README

* Un-Prettier README

* Switch to async loading as the module is 8 KiB

* Switch to `b4a` for digest encoding

* Handle promise errors

* Don't pass `cb` directly to resolved branch
master
Kasper Isager Dalsgarð 3 years ago
committed by GitHub
parent
commit
66a35bc45c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .gitignore
  2. 14
      README.md
  3. 91
      blake2b.js
  4. BIN
      blake2b.wasm
  5. 83
      index.js
  6. 6
      package.json

1
.gitignore

@ -1,2 +1,3 @@
node_modules
package-lock.json
bundle.js

14
README.md

@ -63,22 +63,12 @@ There is a browser example included in [example.html](example.html) and [example
## Contributing
The bulk of this module is implemented in WebAssembly in the [blake2b.wat](blake2b.wat) file.
The format of this file is S-Expressions that can be compiled to their binary WASM representation by doing
The bulk of this module is implemented in WebAssembly in the [blake2b.wat](blake2b.wat) file. To build the thin Javascript wrapper do:
```
wat2wasm blake2b.wat -o blake2b.wasm
npm run compile
```
To build the thin Javascript wrapper for the WASM module use `wat2js`:
```
# also available as `npm run compile`
wat2js blake2b.wat -o blake2b.js
```
If you do not have `wat2wasm` installed follow the instructions here, https://github.com/WebAssembly/wabt
## License
MIT

91
blake2b.js

File diff suppressed because one or more lines are too long

BIN
blake2b.wasm

Binary file not shown.

83
index.js

@ -1,5 +1,10 @@
var assert = require('nanoassert')
var wasm = require('./blake2b')()
var b4a = require('b4a')
var wasm = null
var wasmPromise = typeof WebAssembly !== "undefined" && require('./blake2b')().then(mod => {
wasm = mod
})
var head = 64
var freeList = []
@ -16,7 +21,7 @@ var PERSONALBYTES = module.exports.PERSONALBYTES = 16
function Blake2b (digestLength, key, salt, personal, noAssert) {
if (!(this instanceof Blake2b)) return new Blake2b(digestLength, key, salt, personal, noAssert)
if (!(wasm && wasm.exports)) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)')
if (!wasm) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)')
if (!digestLength) digestLength = 32
if (noAssert !== true) {
@ -45,34 +50,39 @@ function Blake2b (digestLength, key, salt, personal, noAssert) {
this.digestLength = digestLength
this.finalized = false
this.pointer = freeList.pop()
this._memory = new Uint8Array(wasm.memory.buffer)
wasm.memory.fill(0, 0, 64)
wasm.memory[0] = this.digestLength
wasm.memory[1] = key ? key.length : 0
wasm.memory[2] = 1 // fanout
wasm.memory[3] = 1 // depth
this._memory.fill(0, 0, 64)
this._memory[0] = this.digestLength
this._memory[1] = key ? key.length : 0
this._memory[2] = 1 // fanout
this._memory[3] = 1 // depth
if (salt) wasm.memory.set(salt, 32)
if (personal) wasm.memory.set(personal, 48)
if (salt) this._memory.set(salt, 32)
if (personal) this._memory.set(personal, 48)
if (this.pointer + 216 > wasm.memory.length) wasm.realloc(this.pointer + 216) // we need 216 bytes for the state
wasm.exports.blake2b_init(this.pointer, this.digestLength)
if (this.pointer + 216 > this._memory.length) this._realloc(this.pointer + 216) // we need 216 bytes for the state
wasm.blake2b_init(this.pointer, this.digestLength)
if (key) {
this.update(key)
wasm.memory.fill(0, head, head + key.length) // whiteout key
wasm.memory[this.pointer + 200] = 128
this._memory.fill(0, head, head + key.length) // whiteout key
this._memory[this.pointer + 200] = 128
}
}
Blake2b.prototype._realloc = function (size) {
wasm.memory.grow(Math.max(0, Math.ceil(Math.abs(size - this._memory.length) / 65536)))
this._memory = new Uint8Array(wasm.memory.buffer)
}
Blake2b.prototype.update = function (input) {
assert(this.finalized === false, 'Hash instance finalized')
assert(input instanceof Uint8Array, 'input must be Uint8Array or Buffer')
if (head + input.length > wasm.memory.length) wasm.realloc(head + input.length)
wasm.memory.set(input, head)
wasm.exports.blake2b_update(this.pointer, head, head + input.length)
if (head + input.length > this._memory.length) this._realloc(head + input.length)
this._memory.set(input, head)
wasm.blake2b_update(this.pointer, head, head + input.length)
return this
}
@ -81,19 +91,19 @@ Blake2b.prototype.digest = function (enc) {
this.finalized = true
freeList.push(this.pointer)
wasm.exports.blake2b_final(this.pointer)
wasm.blake2b_final(this.pointer)
if (!enc || enc === 'binary') {
return wasm.memory.slice(this.pointer + 128, this.pointer + 128 + this.digestLength)
return this._memory.slice(this.pointer + 128, this.pointer + 128 + this.digestLength)
}
if (enc === 'hex') {
return hexSlice(wasm.memory, this.pointer + 128, this.digestLength)
if (typeof enc === 'string') {
return b4a.toString(this._memory, enc, this.pointer + 128, this.pointer + 128 + this.digestLength)
}
assert(enc instanceof Uint8Array && enc.length >= this.digestLength, 'input must be Uint8Array or Buffer')
for (var i = 0; i < this.digestLength; i++) {
enc[i] = wasm.memory[this.pointer + 128 + i]
enc[i] = this._memory[this.pointer + 128 + i]
}
return enc
@ -102,44 +112,23 @@ Blake2b.prototype.digest = function (enc) {
// libsodium compat
Blake2b.prototype.final = Blake2b.prototype.digest
Blake2b.WASM = wasm && wasm.buffer
Blake2b.WASM = wasm
Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined'
Blake2b.ready = function (cb) {
if (!cb) cb = noop
if (!wasm) return cb(new Error('WebAssembly not supported'))
// backwards compat, can be removed in a new major
var p = new Promise(function (reject, resolve) {
wasm.onload(function (err) {
if (err) resolve()
else reject()
cb(err)
})
})
return p
if (!wasmPromise) return cb(new Error('WebAssembly not supported'))
return wasmPromise.then(() => cb(), cb)
}
Blake2b.prototype.ready = Blake2b.ready
Blake2b.prototype.getPartialHash = function () {
return wasm.memory.slice(this.pointer, this.pointer + 216);
return this._memory.slice(this.pointer, this.pointer + 216);
}
Blake2b.prototype.setPartialHash = function (ph) {
wasm.memory.set(ph, this.pointer);
this._memory.set(ph, this.pointer);
}
function noop () {}
function hexSlice (buf, start, len) {
var str = ''
for (var i = 0; i < len; i++) str += toHex(buf[start + i])
return str
}
function toHex (n) {
if (n < 16) return '0' + n.toString(16)
return n.toString(16)
}

6
package.json

@ -4,17 +4,17 @@
"description": "Blake2b implemented in WASM",
"main": "index.js",
"dependencies": {
"b4a": "^1.0.1",
"nanoassert": "^2.0.0"
},
"devDependencies": {
"blake2b": "^1.2.0",
"browserify": "^14.4.0",
"tape": "^4.6.3",
"wat2js": "^1.1.1",
"wat2wasm": "^1.0.2"
"wasm-tools": "^0.2.0"
},
"scripts": {
"compile": "wat2js blake2b.wat -o blake2b.js",
"compile": "wasm-to-js -f cjs blake2b.wat > blake2b.js",
"demo": "browserify example.js > bundle.js",
"test": "tape test.js"
},

Loading…
Cancel
Save