Browse Source

first commit

master
Mathias Buus 7 years ago
commit
771a3f767d
  1. 2
      .gitignore
  2. 21
      LICENSE
  3. 65
      README.md
  4. BIN
      blake2b.wasm
  5. 2830
      blake2b.wat
  6. 14
      example.html
  7. 12
      example.js
  8. 77
      generate-rounds.js
  9. 94
      index.js
  10. 31
      package.json

2
.gitignore

@ -0,0 +1,2 @@
node_modules
bundle.js

21
LICENSE

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Mathias Buus
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

65
README.md

@ -0,0 +1,65 @@
# blake2b-wasm
Blake2b implemented in WASM
```
npm install blake2b-wasm
```
Works in browsers that support WASM and Node.js 8+.
## Usage
``` js
var blake2b = require('blake2b-wasm')
if (!blake2b.SUPPORTED) {
console.log('WebAssembly not supported by your runtime')
}
blake2b.ready(function (err) {
if (err) throw err
var hash = blake2b()
.update(new Buffer('hello')) // pass in a buffer or uint8array
.update(new Buffer(' '))
.update(new Buffer('world'))
.digest('hex')
console.log('Blake2b hash of "hello world" is %s', hash)
})
```
## API
#### `var hash = blake2b()`
Create a new hash instance
#### `hash.update(data)`
Update the hash with a new piece of data. `data` should be a buffer or uint8array.
#### `var digest = hash.digest([enc])`
Digest the hash.
## Browser demo
There is a browser example included in [example.html](example.html) and [example.js](example.js).
## 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
```
# also available as `npm run compile`
wast2wasm blake2b.wat -o blake2b.wasm
```
If you do not have `wast2wasm` installed follow the instructions here, https://github.com/WebAssembly/wabt
## License
MIT

BIN
blake2b.wasm

Binary file not shown.

2830
blake2b.wat

File diff suppressed because it is too large

14
example.html

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Blake2b-WASM Demo</title>
</head>
<body>
<ol>
<li>Run `npm run demo` if you haven't</li>
<li>Reload this page</li>
<li>Open the console</li>
</ol>
<script src="bundle.js"></script>
</body>
</html>

12
example.js

@ -0,0 +1,12 @@
var blake2b = require('./')
blake2b.ready(function () {
var hash = blake2b()
.update(new Buffer('hello'))
.update(new Buffer(' '))
.update(new Buffer('world'))
.digest('hex')
console.log('Blake2b hash of "hello world" is %s', hash)
})

77
generate-rounds.js

@ -0,0 +1,77 @@
var sigma = [
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] ,
[ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ] ,
[ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ] ,
[ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ] ,
[ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ] ,
[ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ] ,
[ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ] ,
[ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ] ,
[ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ] ,
[ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 ] ,
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ] ,
[ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ]
]
function G (r, i, a, b, c, d) {
return `
;; G(${r}, ${i})
;; ${a} = ${a} + ${b} + $m${sigma[r][2*i+0]}
(set_local ${a} (i64.add (get_local ${a}) (i64.add (get_local ${b}) (get_local $m${sigma[r][2*i+0]}))))
;; ${d} = rotr64(${d} ^ ${a}, 32)
(set_local ${d} (i64.rotr (i64.xor (get_local ${d}) (get_local ${a})) (i64.const 32)))
;; ${c} = ${c} + ${d}
(set_local ${c} (i64.add (get_local ${c}) (get_local ${d})))
;; ${b} = rotr64(${b} ^ ${c}, 24)
(set_local ${b} (i64.rotr (i64.xor (get_local ${b}) (get_local ${c})) (i64.const 24)))
;; ${a} = ${a} + ${b} + $m${sigma[r][2*i+1]}
(set_local ${a} (i64.add (get_local ${a}) (i64.add (get_local ${b}) (get_local $m${sigma[r][2*i+1]}))))
;; ${d} = rotr64(${d} ^ ${a}, 16)
(set_local ${d} (i64.rotr (i64.xor (get_local ${d}) (get_local ${a})) (i64.const 16)))
;; ${c} = ${c} + ${d}
(set_local ${c} (i64.add (get_local ${c}) (get_local ${d})))
;; ${b} = rotr64(${b} ^ ${c}, 63)
(set_local ${b} (i64.rotr (i64.xor (get_local ${b}) (get_local ${c})) (i64.const 63)))`
}
function ROUND (r) {
return `
;; ROUND(${r})
${G(r,0, '$v0', '$v4', '$v8', '$v12')}
${G(r,1, '$v1', '$v5', '$v9', '$v13')}
${G(r,2, '$v2', '$v6', '$v10', '$v14')}
${G(r,3, '$v3', '$v7', '$v11', '$v15')}
${G(r,4, '$v0', '$v5', '$v10', '$v15')}
${G(r,5, '$v1', '$v6', '$v11', '$v12')}
${G(r,6, '$v2', '$v7', '$v8', '$v13')}
${G(r,7, '$v3', '$v4', '$v9', '$v14')}
`
}
// function rotr64 (w, c) {
// i64
// // ( w >> c ) | ( w << ( 64 - c ) )
// rotr64
// }
console.log(
ROUND( 0 ),
ROUND( 1 ),
ROUND( 2 ),
ROUND( 3 ),
ROUND( 4 ),
ROUND( 5 ),
ROUND( 6 ),
ROUND( 7 ),
ROUND( 8 ),
ROUND( 9 ),
ROUND( 10 ),
ROUND( 11 )
)

94
index.js

@ -0,0 +1,94 @@
var fs = require('fs')
var buf = toUint8Array(fs.readFileSync(__dirname + '/blake2b.wasm', 'base64'))
var rdy
var head = 64
var mod = null
var memory = null
var freeList = []
module.exports = Blake2b
function Blake2b () {
if (!(this instanceof Blake2b)) return new Blake2b()
if (!mod) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)')
if (!freeList.length) {
freeList.push(head)
head += 216
}
this.finalized = false
this.pointer = freeList.pop()
mod.blake2b_init(this.pointer, 32)
}
Blake2b.prototype.ready = Blake2b.ready
Blake2b.prototype.update = function (input) {
if (this.finalized) throw new Error('Hash instance finalized')
memory.set(input, head)
mod.blake2b_update(this.pointer, head, head + input.length)
return this
}
Blake2b.prototype.digest = function (enc) {
if (this.finalized) throw new Error('Hash instance finalized')
this.finalized = true
freeList.push(this.pointer)
mod.blake2b_final(this.pointer)
if (!enc || enc === 'binary') return memory.slice(this.pointer + 128, this.pointer + 128 + 32)
if (enc === 'hex') return hexSlice(memory, this.pointer + 128, 32)
for (var i = 0; i < 32; i++) enc[i] = memory[this.pointer + 128 + i]
return enc
}
Blake2b.WASM = buf
Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined'
Blake2b.ready = function (cb) {
if (!cb) cb = noop
if (!Blake2b.SUPPORTED) return cb(new Error('WebAssembly not supported'))
if (!rdy) {
rdy = WebAssembly.instantiate(buf).then(setup)
}
return rdy.then(cb).catch(cb)
}
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)
}
function setup (w) {
mod = w.instance.exports
memory = new Uint8Array(w.instance.exports.memory.buffer)
}
function toUint8Array (s) {
if (typeof atob === 'function') {
return new Uint8Array(atob(s).split('').map(charCodeAt))
}
var b = require('buf' + 'fer')
return new b.Buffer(s, 'base64')
}
function charCodeAt (c) {
return c.charCodeAt(0)
}
window.Blake2b = module.exports

31
package.json

@ -0,0 +1,31 @@
{
"name": "blake2b-wasm",
"version": "0.0.0",
"description": "Blake2b implemented in WASM",
"main": "index.js",
"dependencies": {
"brfs": "^1.4.3"
},
"devDependencies": {
"browserify": "^14.4.0"
},
"browserify": {
"transform": [
"brfs"
]
},
"scripts": {
"compile": "wast2wasm blake2b.wat -o blake2b.wasm",
"demo": "browserify example.js > bundle.js"
},
"repository": {
"type": "git",
"url": "https://github.com/mafintosh/blake2b-wasm.git"
},
"author": "Mathias Buus (@mafintosh)",
"license": "MIT",
"bugs": {
"url": "https://github.com/mafintosh/blake2b-wasm/issues"
},
"homepage": "https://github.com/mafintosh/blake2b-wasm"
}
Loading…
Cancel
Save