mirror of https://github.com/keeweb/keeweb.git
argon2-wasm
This commit is contained in:
parent
9275d74b2b
commit
349fca7643
11
Gruntfile.js
11
Gruntfile.js
|
@ -50,7 +50,8 @@ module.exports = function(grunt) {
|
|||
const webpackConfig = {
|
||||
entry: {
|
||||
app: 'app',
|
||||
vendor: ['jquery', 'underscore', 'backbone', 'kdbxweb', 'baron', 'dropbox', 'pikaday', 'filesaver', 'qrcode', 'argon2']
|
||||
vendor: ['jquery', 'underscore', 'backbone', 'kdbxweb', 'baron', 'dropbox', 'pikaday', 'filesaver', 'qrcode',
|
||||
'argon2-asm', 'argon2-wasm', 'argon2']
|
||||
},
|
||||
output: {
|
||||
path: path.resolve('.', 'tmp/js'),
|
||||
|
@ -77,7 +78,9 @@ module.exports = function(grunt) {
|
|||
pikaday: 'pikaday/pikaday.js',
|
||||
filesaver: 'FileSaver.js/FileSaver.min.js',
|
||||
qrcode: 'jsqrcode/dist/qrcode.min.js',
|
||||
argon2: 'argon2-browser/docs/dist/argon2-asm.min.js',
|
||||
'argon2-asm': 'argon2-browser/docs/dist/argon2-asm.min.js',
|
||||
'argon2-wasm': 'argon2-browser/docs/dist/argon2.wasm',
|
||||
'argon2': 'argon2-browser/docs/dist/argon2.min.js',
|
||||
templates: path.join(__dirname, 'app/templates')
|
||||
}
|
||||
},
|
||||
|
@ -99,7 +102,9 @@ module.exports = function(grunt) {
|
|||
query: { presets: ['es2015'], cacheDirectory: true }
|
||||
},
|
||||
{ test: /\.json$/, loader: 'json-loader' },
|
||||
{ test: /argon2-asm\.min\.js$/, loader: 'exports-loader?Module' }
|
||||
{ test: /argon2-asm\.min\.js$/, loader: 'raw-loader' },
|
||||
{ test: /argon2\.wasm$/, loader: 'base64-loader' },
|
||||
{ test: /argon2\.min\.js/, loader: 'raw-loader' } // exports-loader?Module
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
|
|
|
@ -1,29 +1,33 @@
|
|||
'use strict';
|
||||
|
||||
const kdbxweb = require('kdbxweb');
|
||||
const Logger = require('../util/logger');
|
||||
|
||||
const logger = new Logger('argon2');
|
||||
|
||||
const KdbxwebInit = {
|
||||
init() {
|
||||
kdbxweb.CryptoEngine.argon2 = this.argon2;
|
||||
kdbxweb.CryptoEngine.argon2 = (...args) => this.argon2(...args);
|
||||
},
|
||||
|
||||
argon2(password, salt, memory, iterations, length, parallelism, type, version) {
|
||||
const Module = require('argon2');
|
||||
const passwordLen = password.byteLength;
|
||||
password = Module.allocate(new Uint8Array(password), 'i8', Module.ALLOC_NORMAL);
|
||||
const saltLen = salt.byteLength;
|
||||
salt = Module.allocate(new Uint8Array(salt), 'i8', Module.ALLOC_NORMAL);
|
||||
const hash = Module.allocate(new Array(length), 'i8', Module.ALLOC_NORMAL);
|
||||
const encodedLen = 512;
|
||||
const encoded = Module.allocate(new Array(encodedLen), 'i8', Module.ALLOC_NORMAL);
|
||||
// jshint camelcase:false
|
||||
try {
|
||||
return this.loadRuntime().then((Module) => {
|
||||
const passwordLen = password.byteLength;
|
||||
password = Module.allocate(new Uint8Array(password), 'i8', Module.ALLOC_NORMAL);
|
||||
const saltLen = salt.byteLength;
|
||||
salt = Module.allocate(new Uint8Array(salt), 'i8', Module.ALLOC_NORMAL);
|
||||
const hash = Module.allocate(new Array(length), 'i8', Module.ALLOC_NORMAL);
|
||||
const encodedLen = 512;
|
||||
const encoded = Module.allocate(new Array(encodedLen), 'i8', Module.ALLOC_NORMAL);
|
||||
|
||||
const ts = logger.ts();
|
||||
const res = Module._argon2_hash(iterations, memory, parallelism,
|
||||
password, passwordLen, salt, saltLen,
|
||||
hash, length, encoded, encodedLen, type, version);
|
||||
if (res) {
|
||||
return Promise.reject('Argon2 error ' + res);
|
||||
throw new Error('Argon2 error ' + res);
|
||||
}
|
||||
logger.debug('Hash computed', logger.ts(ts));
|
||||
const hashArr = new Uint8Array(length);
|
||||
for (let i = 0; i < length; i++) {
|
||||
hashArr[i] = Module.HEAP8[hash + i];
|
||||
|
@ -32,10 +36,57 @@ const KdbxwebInit = {
|
|||
Module._free(salt);
|
||||
Module._free(hash);
|
||||
Module._free(encoded);
|
||||
return Promise.resolve(hashArr);
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
return hashArr;
|
||||
});
|
||||
},
|
||||
|
||||
loadRuntime: function() {
|
||||
if (this.runtimeModule) {
|
||||
return Promise.resolve(this.runtimeModule);
|
||||
}
|
||||
if (!global.WebAssembly) {
|
||||
return this.loadAsmJsFallbackRuntime();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const loadTimeout = setTimeout(() => reject('timeout'), 1000);
|
||||
try {
|
||||
const ts = logger.ts();
|
||||
const argon2LoaderCode = require('argon2');
|
||||
const wasmBinaryBase64 = require('argon2-wasm');
|
||||
const wasmBinary = kdbxweb.ByteUtils.base64ToBytes(wasmBinaryBase64).buffer;
|
||||
const Module = global.Module = {
|
||||
print: (...args) => logger.debug(...args),
|
||||
printErr: (...args) => logger.debug(...args),
|
||||
wasmBinary: wasmBinary,
|
||||
wasmJSMethod: 'native-wasm',
|
||||
postRun: () => {
|
||||
logger.debug('WebAssembly runtime loaded', logger.ts(ts));
|
||||
clearTimeout(loadTimeout);
|
||||
this.runtimeModule = Module;
|
||||
resolve(this.runtimeModule);
|
||||
}
|
||||
};
|
||||
global.eval(argon2LoaderCode); // eslint-disable-line
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
}).catch(err => {
|
||||
logger.warn('WebAssembly error', err);
|
||||
return this.loadAsmJsFallbackRuntime();
|
||||
});
|
||||
},
|
||||
|
||||
loadAsmJsFallbackRuntime: function() {
|
||||
logger.debug('Loading asm.js fallback runtime');
|
||||
return new Promise(resolve => {
|
||||
const ts = logger.ts();
|
||||
global.Module = undefined;
|
||||
const argon2Code = require('argon2-asm');
|
||||
global.eval(argon2Code); // eslint-disable-line
|
||||
this.runtimeModule = global.Module;
|
||||
logger.debug('Fallback runtime loaded', logger.ts(ts));
|
||||
resolve(this.runtimeModule);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,6 @@
|
|||
"FileSaver.js": "eligrey/FileSaver.js",
|
||||
"jquery": "3.1.0",
|
||||
"jsqrcode": "antelle/jsqrcode#0.1.3",
|
||||
"argon2-browser": "^0.0.2"
|
||||
"argon2-browser": "0.0.5"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue