-
Notifications
You must be signed in to change notification settings - Fork 1
/
pbkdf2Wasm.js
144 lines (132 loc) · 4.07 KB
/
pbkdf2Wasm.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* Most of this file (i.e. pretty much 99% of it) has been copied from @bitjson's secp256k1Wasm.ts in the bitcoin-ts repo on GitHub
* You can thank that guy for getting me into WASM.
*
* Perhaps I should expand upon this file to make a fast generic WASM loader.
*/
const isLittleEndian = (buffer) => {
const littleEndian = true;
const notLittleEndian = false;
const heap16 = new Int16Array(buffer);
const heap32 = new Int32Array(buffer);
const heapU8 = new Uint8Array(buffer);
heap32[0] = 1668509029;
heap16[1] = 25459;
return heapU8[2] !== 115 || heapU8[3] !== 99
? notLittleEndian
: littleEndian;
};
const alignMemory = (factor, size) =>
Math.ceil(size / factor) * factor;
const instantiatePbkdf2WasmBytes = async (bytes) => {
const STACK_ALIGN = 16;
const GLOBAL_BASE = 1024;
const WASM_PAGE_SIZE = 65536;
const TOTAL_STACK = 5242880;
const TOTAL_MEMORY = 16777216;
const wasmMemory = new WebAssembly.Memory({
initial: TOTAL_MEMORY / WASM_PAGE_SIZE,
maximum: TOTAL_MEMORY / WASM_PAGE_SIZE
});
if (!isLittleEndian(wasmMemory.buffer)) {
throw new Error('Runtime error: expected the system to be little-endian.');
}
const STATIC_BASE = GLOBAL_BASE;
const STATICTOP_INITIAL = STATIC_BASE + 67696 + 16;
const DYNAMICTOP_PTR = STATICTOP_INITIAL;
const DYNAMICTOP_PTR_SIZE = 4;
const STATICTOP = (STATICTOP_INITIAL + DYNAMICTOP_PTR_SIZE + 15) & -16;
const STACKTOP = alignMemory(STACK_ALIGN, STATICTOP);
const STACK_BASE = STACKTOP;
const STACK_MAX = STACK_BASE + TOTAL_STACK;
const DYNAMIC_BASE = alignMemory(STACK_ALIGN, STACK_MAX);
const heapU8 = new Uint8Array(wasmMemory.buffer);
const heap32 = new Int32Array(wasmMemory.buffer);
const heapU32 = new Uint32Array(wasmMemory.buffer);
heap32[DYNAMICTOP_PTR >> 2] = DYNAMIC_BASE;
const TABLE_SIZE = 6;
const MAX_TABLE_SIZE = 6;
let sha512Callback;
const functionPointers = [(hashOutPtr, dataPtr, dataLen) => {
sha512Callback(hashOutPtr, dataPtr, dataLen);
}];
let getErrNoLocation;
const env = {
DYNAMICTOP_PTR,
STACKTOP,
___setErrNo: (value) => {
if (getErrNoLocation !== undefined) {
heap32[getErrNoLocation() >> 2] = value;
}
return value;
},
___assert_fail: (...args) => {
let str = "pbkdf2 WASM asserstion failed:";
for (let i = 0; i < args.length; i+=1){
str += " "+String(args[i]);
}
throw new Error(str);
},
_emscripten_memcpy_big: (
dest,
src,
num
) => {
heapU8.set(heapU8.subarray(src, src + num), dest);
return dest;
},
abort: (err = 'Secp256k1 Error') => {
throw new Error(err);
},
abortOnCannotGrowMemory: () => {
throw new Error('Secp256k1 Error: abortOnCannotGrowMemory was called.');
},
enlargeMemory: () => {
throw new Error('Secp256k1 Error: enlargeMemory was called.');
},
getTotalMemory: () => TOTAL_MEMORY,
jsCall_viii: (index, ...args) => {
functionPointers[index](...args);
}
};
const info = {
env: {
...env,
memory: wasmMemory,
memoryBase: STATIC_BASE,
table: new WebAssembly.Table({
element: 'anyfunc',
initial: TABLE_SIZE,
maximum: MAX_TABLE_SIZE
}),
tableBase: 0
},
global: { NaN, Infinity }
};
let result = await WebAssembly.instantiate(bytes, info);
result.instance.exports._sha512_ptr_set(1);
const exports = result.instance.exports;
return {
heapU8: heapU8,
malloc: exports._malloc,
free: exports._free,
setSha512Callback: (f) => {
sha512Callback = f;
},
xorStr: (bufferPtr, bufferLen, val) => {
exports._xorstr(bufferPtr, bufferLen, val);
},
xorStrs: (buffer1Ptr, buffer2Ptr, bufferLen) => {
exports._xorstrs(buffer1Ptr, buffer2Ptr, bufferLen);
},
hmacSha512: (resultPtr, saltPtr, saltLen, keyPtr, keyLen) => {
exports._hmac_sha512(resultPtr, saltPtr, saltLen, keyPtr, keyLen);
},
pbkdf2Sha512: (resultPtr, saltPtr, saltLen, keyPtr, keyLen, iterations) => {
exports._pbkdf2_sha512(resultPtr, saltPtr, saltLen, keyPtr, keyLen, iterations);
}
}
}
module.exports = {
instantiatePbkdf2WasmBytes
}