argon2-wasm

This commit is contained in:
antelle 2017-02-04 14:17:33 +01:00
parent 9275d74b2b
commit 349fca7643
3 changed files with 75 additions and 19 deletions

View File

@ -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: [

View File

@ -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);
});
}
};

View File

@ -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"
}
}