1 | var fs = require('fs')
|
2 | var buf = toUint8Array(fs.readFileSync(__dirname + '/blake2b.wasm', 'base64'))
|
3 | var rdy
|
4 |
|
5 | var head = 64
|
6 | var mod = null
|
7 | var memory = null
|
8 | var freeList = []
|
9 |
|
10 | module.exports = Blake2b
|
11 |
|
12 | function Blake2b (digestLength, key, salt, personal) {
|
13 | if (!(this instanceof Blake2b)) return new Blake2b(digestLength, key, salt, personal)
|
14 | if (!mod) throw new Error('WASM not loaded. Wait for Blake2b.ready(cb)')
|
15 |
|
16 | if (!freeList.length) {
|
17 | freeList.push(head)
|
18 | head += 216
|
19 | }
|
20 |
|
21 | this.digestLength = digestLength || 32
|
22 | this.finalized = false
|
23 | this.pointer = freeList.pop()
|
24 |
|
25 | memory.fill(0, 0, 64)
|
26 | memory[0] = this.digestLength
|
27 | memory[1] = key ? key.length : 0
|
28 | memory[2] = 1
|
29 | memory[3] = 1
|
30 |
|
31 | if (salt) memory.set(salt, 32)
|
32 | if (personal) memory.set(personal, 48)
|
33 |
|
34 | mod.blake2b_init(this.pointer, this.digestLength)
|
35 |
|
36 | if (key) {
|
37 | this.update(key)
|
38 | memory.fill(0, head, head + key.length)
|
39 | memory[this.pointer + 200] = 128
|
40 | }
|
41 | }
|
42 |
|
43 | Blake2b.prototype.ready = Blake2b.ready
|
44 |
|
45 | Blake2b.prototype.update = function (input) {
|
46 | if (this.finalized) throw new Error('Hash instance finalized')
|
47 |
|
48 | memory.set(input, head)
|
49 | mod.blake2b_update(this.pointer, head, head + input.length)
|
50 | return this
|
51 | }
|
52 |
|
53 | Blake2b.prototype.digest = function (enc) {
|
54 | if (this.finalized) throw new Error('Hash instance finalized')
|
55 | this.finalized = true
|
56 |
|
57 | freeList.push(this.pointer)
|
58 | mod.blake2b_final(this.pointer)
|
59 |
|
60 | if (!enc || enc === 'binary') {
|
61 | return memory.slice(this.pointer + 128, this.pointer + 128 + this.digestLength)
|
62 | }
|
63 |
|
64 | if (enc === 'hex') {
|
65 | return hexSlice(memory, this.pointer + 128, this.digestLength)
|
66 | }
|
67 |
|
68 | for (var i = 0; i < this.digestLength; i++) {
|
69 | enc[i] = memory[this.pointer + 128 + i]
|
70 | }
|
71 |
|
72 | return enc
|
73 | }
|
74 |
|
75 | Blake2b.WASM = buf
|
76 | Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined'
|
77 |
|
78 | Blake2b.ready = function (cb) {
|
79 | if (!cb) cb = noop
|
80 | if (!Blake2b.SUPPORTED) return cb(new Error('WebAssembly not supported'))
|
81 |
|
82 | if (!rdy) {
|
83 | rdy = WebAssembly.instantiate(buf).then(setup)
|
84 | }
|
85 |
|
86 | return rdy.then(cb).catch(cb)
|
87 | }
|
88 |
|
89 | function noop () {}
|
90 |
|
91 | function hexSlice (buf, start, len) {
|
92 | var str = ''
|
93 | for (var i = 0; i < len; i++) str += toHex(buf[start + i])
|
94 | return str
|
95 | }
|
96 |
|
97 | function toHex (n) {
|
98 | if (n < 16) return '0' + n.toString(16)
|
99 | return n.toString(16)
|
100 | }
|
101 |
|
102 | function setup (w) {
|
103 | mod = w.instance.exports
|
104 | memory = new Uint8Array(w.instance.exports.memory.buffer)
|
105 | }
|
106 |
|
107 | function toUint8Array (s) {
|
108 | if (typeof atob === 'function') {
|
109 | return new Uint8Array(atob(s).split('').map(charCodeAt))
|
110 | }
|
111 | var b = require('buf' + 'fer')
|
112 | return new b.Buffer(s, 'base64')
|
113 | }
|
114 |
|
115 | function charCodeAt (c) {
|
116 | return c.charCodeAt(0)
|
117 | }
|