1 | (function (root, factory) {
|
2 | if (typeof define === 'function' && define.amd) {
|
3 | define([], factory);
|
4 | } else if (typeof module === 'object' && module.exports) {
|
5 | module.exports = factory();
|
6 | } else {
|
7 | root.argon2 = factory();
|
8 | }
|
9 | })(typeof self !== 'undefined' ? self : this, function () {
|
10 | const global = typeof self !== 'undefined' ? self : this;
|
11 |
|
12 | |
13 |
|
14 |
|
15 | const ArgonType = {
|
16 | Argon2d: 0,
|
17 | Argon2i: 1,
|
18 | Argon2id: 2,
|
19 | };
|
20 |
|
21 | function loadModule(mem) {
|
22 | if (loadModule._promise) {
|
23 | return loadModule._promise;
|
24 | }
|
25 | if (loadModule._module) {
|
26 | return Promise.resolve(loadModule._module);
|
27 | }
|
28 | let promise;
|
29 | if (
|
30 | global.process &&
|
31 | global.process.versions &&
|
32 | global.process.versions.node
|
33 | ) {
|
34 | promise = loadWasmModule().then(
|
35 | (Module) =>
|
36 | new Promise((resolve) => {
|
37 | Module.postRun = () => resolve(Module);
|
38 | })
|
39 | );
|
40 | } else {
|
41 | promise = loadWasmBinary().then((wasmBinary) => {
|
42 | const wasmMemory = mem ? createWasmMemory(mem) : undefined;
|
43 | return initWasm(wasmBinary, wasmMemory);
|
44 | });
|
45 | }
|
46 | loadModule._promise = promise;
|
47 | return promise.then((Module) => {
|
48 | loadModule._module = Module;
|
49 | delete loadModule._promise;
|
50 | return Module;
|
51 | });
|
52 | }
|
53 |
|
54 | function initWasm(wasmBinary, wasmMemory) {
|
55 | return new Promise((resolve) => {
|
56 | global.Module = {
|
57 | wasmBinary,
|
58 | wasmMemory,
|
59 | postRun() {
|
60 | resolve(Module);
|
61 | },
|
62 | };
|
63 | return loadWasmModule();
|
64 | });
|
65 | }
|
66 |
|
67 | function loadWasmModule() {
|
68 | if (global.loadArgon2WasmModule) {
|
69 | return global.loadArgon2WasmModule();
|
70 | }
|
71 | if (typeof require === 'function') {
|
72 | return Promise.resolve(require('../dist/argon2.js'));
|
73 | }
|
74 | return import('../dist/argon2.js');
|
75 | }
|
76 |
|
77 | function loadWasmBinary() {
|
78 | if (global.loadArgon2WasmBinary) {
|
79 | return global.loadArgon2WasmBinary();
|
80 | }
|
81 | if (typeof require === 'function') {
|
82 | return Promise.resolve(require('../dist/argon2.wasm')).then(
|
83 | (wasmModule) => {
|
84 | return decodeWasmBinary(wasmModule);
|
85 | }
|
86 | );
|
87 | }
|
88 | const wasmPath =
|
89 | global.argon2WasmPath ||
|
90 | 'node_modules/argon2-browser/dist/argon2.wasm';
|
91 | return fetch(wasmPath)
|
92 | .then((response) => response.arrayBuffer())
|
93 | .then((ab) => new Uint8Array(ab));
|
94 | }
|
95 |
|
96 | function decodeWasmBinary(base64) {
|
97 | const text = atob(base64);
|
98 | const binary = new Uint8Array(new ArrayBuffer(text.length));
|
99 | for (let i = 0; i < text.length; i++) {
|
100 | binary[i] = text.charCodeAt(i);
|
101 | }
|
102 | return binary;
|
103 | }
|
104 |
|
105 | function createWasmMemory(mem) {
|
106 | const KB = 1024;
|
107 | const MB = 1024 * KB;
|
108 | const GB = 1024 * MB;
|
109 | const WASM_PAGE_SIZE = 64 * KB;
|
110 |
|
111 | const totalMemory = (2 * GB - 64 * KB) / WASM_PAGE_SIZE;
|
112 | const initialMemory = Math.min(
|
113 | Math.max(Math.ceil((mem * KB) / WASM_PAGE_SIZE), 256) + 256,
|
114 | totalMemory
|
115 | );
|
116 |
|
117 | return new WebAssembly.Memory({
|
118 | initial: initialMemory,
|
119 | maximum: totalMemory,
|
120 | });
|
121 | }
|
122 |
|
123 | function allocateArray(Module, arr) {
|
124 | return Module.allocate(arr, 'i8', Module.ALLOC_NORMAL);
|
125 | }
|
126 |
|
127 | function allocateArrayStr(Module, arr) {
|
128 | const nullTerminatedArray = new Uint8Array([...arr, 0]);
|
129 | return allocateArray(Module, nullTerminatedArray);
|
130 | }
|
131 |
|
132 | function encodeUtf8(str) {
|
133 | if (typeof str !== 'string') {
|
134 | return str;
|
135 | }
|
136 | if (typeof TextEncoder === 'function') {
|
137 | return new TextEncoder().encode(str);
|
138 | } else if (typeof Buffer === 'function') {
|
139 | return Buffer.from(str);
|
140 | } else {
|
141 | throw new Error("Don't know how to encode UTF8");
|
142 | }
|
143 | }
|
144 |
|
145 | |
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 | function argon2Hash(params) {
|
166 | const mCost = params.mem || 1024;
|
167 | return loadModule(mCost).then((Module) => {
|
168 | const tCost = params.time || 1;
|
169 | const parallelism = params.parallelism || 1;
|
170 | const pwdEncoded = encodeUtf8(params.pass);
|
171 | const pwd = allocateArrayStr(Module, pwdEncoded);
|
172 | const pwdlen = pwdEncoded.length;
|
173 | const saltEncoded = encodeUtf8(params.salt);
|
174 | const salt = allocateArrayStr(Module, saltEncoded);
|
175 | const saltlen = saltEncoded.length;
|
176 | const argon2Type = params.type || ArgonType.Argon2d;
|
177 | const hash = Module.allocate(
|
178 | new Array(params.hashLen || 24),
|
179 | 'i8',
|
180 | Module.ALLOC_NORMAL
|
181 | );
|
182 | const secret = params.secret
|
183 | ? allocateArray(Module, params.secret)
|
184 | : 0;
|
185 | const secretlen = params.secret ? params.secret.byteLength : 0;
|
186 | const ad = params.ad ? allocateArray(Module, params.ad) : 0;
|
187 | const adlen = params.ad ? params.ad.byteLength : 0;
|
188 | const hashlen = params.hashLen || 24;
|
189 | const encodedlen = Module._argon2_encodedlen(
|
190 | tCost,
|
191 | mCost,
|
192 | parallelism,
|
193 | saltlen,
|
194 | hashlen,
|
195 | argon2Type
|
196 | );
|
197 | const encoded = Module.allocate(
|
198 | new Array(encodedlen + 1),
|
199 | 'i8',
|
200 | Module.ALLOC_NORMAL
|
201 | );
|
202 | const version = 0x13;
|
203 | let err;
|
204 | let res;
|
205 | try {
|
206 | res = Module._argon2_hash_ext(
|
207 | tCost,
|
208 | mCost,
|
209 | parallelism,
|
210 | pwd,
|
211 | pwdlen,
|
212 | salt,
|
213 | saltlen,
|
214 | hash,
|
215 | hashlen,
|
216 | encoded,
|
217 | encodedlen,
|
218 | argon2Type,
|
219 | secret,
|
220 | secretlen,
|
221 | ad,
|
222 | adlen,
|
223 | version
|
224 | );
|
225 | } catch (e) {
|
226 | err = e;
|
227 | }
|
228 | let result;
|
229 | if (res === 0 && !err) {
|
230 | let hashStr = '';
|
231 | const hashArr = new Uint8Array(hashlen);
|
232 | for (let i = 0; i < hashlen; i++) {
|
233 | const byte = Module.HEAP8[hash + i];
|
234 | hashArr[i] = byte;
|
235 | hashStr += ('0' + (0xff & byte).toString(16)).slice(-2);
|
236 | }
|
237 | const encodedStr = Module.UTF8ToString(encoded);
|
238 | result = {
|
239 | hash: hashArr,
|
240 | hashHex: hashStr,
|
241 | encoded: encodedStr,
|
242 | };
|
243 | } else {
|
244 | try {
|
245 | if (!err) {
|
246 | err = Module.UTF8ToString(
|
247 | Module._argon2_error_message(res)
|
248 | );
|
249 | }
|
250 | } catch (e) {}
|
251 | result = { message: err, code: res };
|
252 | }
|
253 | try {
|
254 | Module._free(pwd);
|
255 | Module._free(salt);
|
256 | Module._free(hash);
|
257 | Module._free(encoded);
|
258 | if (ad) {
|
259 | Module._free(ad);
|
260 | }
|
261 | if (secret) {
|
262 | Module._free(secret);
|
263 | }
|
264 | } catch (e) {}
|
265 | if (err) {
|
266 | throw result;
|
267 | } else {
|
268 | return result;
|
269 | }
|
270 | });
|
271 | }
|
272 |
|
273 | |
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 |
|
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 | function argon2Verify(params) {
|
290 | return loadModule().then((Module) => {
|
291 | const pwdEncoded = encodeUtf8(params.pass);
|
292 | const pwd = allocateArrayStr(Module, pwdEncoded);
|
293 | const pwdlen = pwdEncoded.length;
|
294 | const encEncoded = encodeUtf8(params.encoded);
|
295 | const enc = allocateArrayStr(Module, encEncoded);
|
296 | let argon2Type = params.type;
|
297 | if (argon2Type === undefined) {
|
298 | let typeStr = params.encoded.split('$')[1];
|
299 | if (typeStr) {
|
300 | typeStr = typeStr.replace('a', 'A');
|
301 | argon2Type = ArgonType[typeStr] || ArgonType.Argon2d;
|
302 | }
|
303 | }
|
304 | let err;
|
305 | let res;
|
306 | try {
|
307 | res = Module._argon2_verify(enc, pwd, pwdlen, argon2Type);
|
308 | } catch (e) {
|
309 | err = e;
|
310 | }
|
311 | let result;
|
312 | if (res || err) {
|
313 | try {
|
314 | if (!err) {
|
315 | err = Module.UTF8ToString(
|
316 | Module._argon2_error_message(res)
|
317 | );
|
318 | }
|
319 | } catch (e) {}
|
320 | result = { message: err, code: res };
|
321 | }
|
322 | try {
|
323 | Module._free(pwd);
|
324 | Module._free(enc);
|
325 | } catch (e) {}
|
326 | if (err) {
|
327 | throw result;
|
328 | } else {
|
329 | return result;
|
330 | }
|
331 | });
|
332 | }
|
333 |
|
334 | function unloadRuntime() {
|
335 | if (loadModule._module) {
|
336 | loadModule._module.unloadRuntime();
|
337 | delete loadModule._promise;
|
338 | delete loadModule._module;
|
339 | }
|
340 | }
|
341 |
|
342 | return {
|
343 | ArgonType,
|
344 | hash: argon2Hash,
|
345 | verify: argon2Verify,
|
346 | unloadRuntime,
|
347 | };
|
348 | });
|