/** * High level crypto api that invokes native crypto (if available) and * gracefully degrades to JS crypto (if unavailable) */ define(function(require) { 'use strict'; var aes = require('js/crypto/aes-gcm'), pbkdf2 = require('js/crypto/pbkdf2'), config = require('js/app-config').config, axe = require('axe'); var PBKDF2_WORKER = '/crypto/pbkdf2-worker.js'; var Crypto = function() {}; /** * Encrypt plaintext using AES-GCM. * @param {String} plaintext The input string in UTF-16 * @param {String} key The base64 encoded key * @param {String} iv The base64 encoded IV * @param {Function} callback(error, ciphertext) * @return {String} The base64 encoded ciphertext */ Crypto.prototype.encrypt = function(plaintext, key, iv, callback) { var ct; try { ct = aes.encrypt(plaintext, key, iv); } catch (err) { callback(err); return; } callback(null, ct); }; /** * Decrypt ciphertext suing AES-GCM * @param {String} ciphertext The base64 encoded ciphertext * @param {String} key The base64 encoded key * @param {String} iv The base64 encoded IV * @param {Function} callback(error, plaintext) * @return {String} The decrypted plaintext in UTF-16 */ Crypto.prototype.decrypt = function(ciphertext, key, iv, callback) { var pt; try { pt = aes.decrypt(ciphertext, key, iv); } catch (err) { callback(err); return; } callback(null, pt); }; /** * Do PBKDF2 key derivation in a WebWorker thread */ Crypto.prototype.deriveKey = function(password, salt, keySize, callback) { startWorker({ script: PBKDF2_WORKER, args: { password: password, salt: salt, keySize: keySize }, callback: callback, noWorker: function() { return pbkdf2.getKey(password, salt, keySize); } }); }; // // helper functions // function startWorker(options) { // check for WebWorker support if (window.Worker) { // init webworker thread var worker = new Worker(config.workerPath + options.script); worker.onmessage = function(e) { if (e.data.err) { options.callback(e.data.err); return; } // return result from the worker options.callback(null, e.data); }; worker.onerror = function(e) { // show error message in logger axe.error('Error handling web worker: Line ' + e.lineno + ' in ' + e.filename + ': ' + e.message); // return error options.callback({ errMsg: (e.message) ? e.message : e }); return; }; // send data to the worker worker.postMessage(options.args); return; } // no WebWorker support... do synchronous call var result; try { result = options.noWorker(); } catch (e) { // return error options.callback({ errMsg: (e.message) ? e.message : e }); return; } options.callback(null, result); } return Crypto; });