UNPKG

2.7 kBJavaScriptView Raw
1var fs = require('fs')
2var buf = toUint8Array(fs.readFileSync(__dirname + '/blake2b.wasm', 'base64'))
3var rdy
4
5var head = 64
6var mod = null
7var memory = null
8var freeList = []
9
10module.exports = Blake2b
11
12function 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 // fanout
29 memory[3] = 1 // depth
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) // whiteout key
39 memory[this.pointer + 200] = 128
40 }
41}
42
43Blake2b.prototype.ready = Blake2b.ready
44
45Blake2b.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
53Blake2b.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
75Blake2b.WASM = buf
76Blake2b.SUPPORTED = typeof WebAssembly !== 'undefined'
77
78Blake2b.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
89function noop () {}
90
91function 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
97function toHex (n) {
98 if (n < 16) return '0' + n.toString(16)
99 return n.toString(16)
100}
101
102function setup (w) {
103 mod = w.instance.exports
104 memory = new Uint8Array(w.instance.exports.memory.buffer)
105}
106
107function 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
115function charCodeAt (c) {
116 return c.charCodeAt(0)
117}