diff --git a/src/js/crypto/aes-batch-worker.js b/src/js/crypto/aes-batch-worker.js index d16bea0..d24e8a8 100644 --- a/src/js/crypto/aes-batch-worker.js +++ b/src/js/crypto/aes-batch-worker.js @@ -13,18 +13,18 @@ */ self.onmessage = function(e) { - var args = e.data, + var i = e.data, output = null, aes = new app.crypto.AesCBC(forge), util = new app.crypto.Util(null, null); - if (args.type === 'encrypt' && args.list) { + if (i.type === 'encrypt' && i.list) { // start encryption - output = util.encryptList(aes, args.list); + output = util.encryptList(aes, i.list); - } else if (args.type === 'decrypt' && args.list) { + } else if (i.type === 'decrypt' && i.list) { // start decryption - output = util.decryptList(aes, args.list); + output = util.decryptList(aes, i.list); } else { throw 'Not all arguments for web worker crypto are defined!'; diff --git a/src/js/crypto/aes-worker.js b/src/js/crypto/aes-worker.js index a3b0f77..8551618 100644 --- a/src/js/crypto/aes-worker.js +++ b/src/js/crypto/aes-worker.js @@ -12,17 +12,17 @@ */ self.onmessage = function(e) { - var args = e.data, + var i = e.data, output = null, aes = new app.crypto.AesCBC(forge); - if (args.type === 'encrypt' && args.plaintext && args.key && args.iv) { + if (i.type === 'encrypt' && i.plaintext && i.key && i.iv) { // start encryption - output = aes.encrypt(args.plaintext, args.key, args.iv); + output = aes.encrypt(i.plaintext, i.key, i.iv); - } else if (args.type === 'decrypt' && args.ciphertext && args.key && args.iv) { + } else if (i.type === 'decrypt' && i.ciphertext && i.key && i.iv) { // start decryption - output = aes.decrypt(args.ciphertext, args.key, args.iv); + output = aes.decrypt(i.ciphertext, i.key, i.iv); } else { throw 'Not all arguments for web worker crypto are defined!'; diff --git a/src/js/crypto/crypto-batch-worker.js b/src/js/crypto/crypto-batch-worker.js new file mode 100644 index 0000000..7198d5f --- /dev/null +++ b/src/js/crypto/crypto-batch-worker.js @@ -0,0 +1,41 @@ +(function() { + 'use strict'; + + // import web worker dependencies + importScripts('../../lib/forge/forge.rsa.bundle.js'); + importScripts('../app-config.js'); + importScripts('./aes-cbc.js'); + importScripts('./rsa.js'); + importScripts('./util.js'); + + /** + * In the web worker thread context, 'this' and 'self' can be used as a global + * variable namespace similar to the 'window' object in the main thread + */ + self.onmessage = function(e) { + + var i = e.data, + output = null, + util = new app.crypto.Util(null, null), + aes = new app.crypto.AesCBC(forge), + rsa = new app.crypto.RSA(forge, util); + + rsa.init(i.pubkeyPem, i.privkeyPem); + + if (i.type === 'encrypt' && i.list) { + // start encryption + output = util.encryptListForUser(aes, rsa, i.list); + + } else if (i.type === 'decrypt' && i.list) { + // start decryption + output = util.decryptListForUser(aes, rsa, i.list); + + } else { + throw 'Not all arguments for web worker crypto are defined!'; + } + + // pass output back to main thread + self.postMessage(output); + }; + +}()); \ No newline at end of file diff --git a/src/js/crypto/crypto.js b/src/js/crypto/crypto.js index adb3398..e463a5a 100644 --- a/src/js/crypto/crypto.js +++ b/src/js/crypto/crypto.js @@ -224,55 +224,47 @@ app.crypto.Crypto = function(window, util) { envelopes.push(envelope); }); - // encrypt list - this.aesEncryptList(envelopes, function(encryptedList) { + if (window.Worker) { - // encrypt keys for user - encryptedList.forEach(function(i) { - // process new values - i.itemIV = i.iv; - i.encryptedKey = rsa.encrypt(i.key); - i.keyIV = rsa.sign([i.itemIV, i.encryptedKey, i.ciphertext]); - // delete old ones - delete i.iv; - delete i.key; + var keypair = rsa.exportKeys(); + + var worker = new Worker(app.config.workerPath + '/crypto/crypto-batch-worker.js'); + worker.onmessage = function(e) { + callback(null, e.data); + }; + worker.postMessage({ + type: 'encrypt', + list: envelopes, + pubkeyPem: keypair.pubkeyPem, + privkeyPem: keypair.privkeyPem }); + } else { + var encryptedList = util.encryptListForUser(aes, rsa, envelopes); callback(null, encryptedList); - }); + } }; - this.decryptListForUser = function(encryptedList, recipientPubkey, callback) { - var list = [], - self = this; + this.decryptListForUser = function(list, recipientPubkey, callback) { + if (window.Worker) { - // decrypt keys for user - encryptedList.forEach(function(i) { - // verify signature - if (!rsa.verify([i.itemIV, i.encryptedKey, i.ciphertext], i.keyIV)) { - callback({ - errMsg: 'Verifying RSA signature failed!' - }); - return; - } - // precoess new values - i.iv = i.itemIV; - i.key = rsa.decrypt(i.encryptedKey); - // delete old values - delete i.keyIV; - delete i.itemIV; - delete i.encryptedKey; - }); + var keypair = rsa.exportKeys(); - // decrypt list - this.aesDecryptList(encryptedList, function(decryptedList) { - // add plaintext to list - decryptedList.forEach(function(i) { - list.push(i.plaintext); + var worker = new Worker(app.config.workerPath + '/crypto/crypto-batch-worker.js'); + worker.onmessage = function(e) { + callback(null, e.data); + }; + worker.postMessage({ + type: 'decrypt', + list: list, + pubkeyPem: keypair.pubkeyPem, + privkeyPem: keypair.privkeyPem }); - callback(null, list); - }); + } else { + var decryptedList = util.decryptListForUser(aes, rsa, list); + callback(null, decryptedList); + } }; }; \ No newline at end of file diff --git a/src/js/crypto/nacl-worker.js b/src/js/crypto/nacl-worker.js index 7fada0d..00bccda 100644 --- a/src/js/crypto/nacl-worker.js +++ b/src/js/crypto/nacl-worker.js @@ -10,24 +10,24 @@ */ self.onmessage = function(e) { - var args = e.data, + var i = e.data, output = null; - if (args.type === 'keygen') { + if (i.type === 'keygen') { // generate keypair - if (args.seed) { - output = nacl.crypto_box_keypair_from_seed(args.seed); + if (i.seed) { + output = nacl.crypto_box_keypair_from_seed(i.seed); } else { output = nacl.crypto_box_keypair(); } - } else if (args.type === 'encrypt' && args.plaintext && args.nonce && args.recipientPk && args.senderSk) { + } else if (i.type === 'encrypt' && i.plaintext && i.nonce && i.recipientPk && i.senderSk) { // start encryption - output = nacl.crypto_box(args.plaintext, args.nonce, args.recipientPk, args.senderSk); + output = nacl.crypto_box(i.plaintext, i.nonce, i.recipientPk, i.senderSk); - } else if (args.type === 'decrypt' && args.ciphertext && args.nonce && args.senderPk && args.recipienSk) { + } else if (i.type === 'decrypt' && i.ciphertext && i.nonce && i.senderPk && i.recipienSk) { // start decryption - output = nacl.crypto_box_open(args.ciphertext, args.nonce, args.senderPk, args.recipienSk); + output = nacl.crypto_box_open(i.ciphertext, i.nonce, i.senderPk, i.recipienSk); } else { throw 'Not all arguments for web worker crypto are defined!'; diff --git a/src/js/crypto/pbkdf2-worker.js b/src/js/crypto/pbkdf2-worker.js index 3a97274..37765d8 100644 --- a/src/js/crypto/pbkdf2-worker.js +++ b/src/js/crypto/pbkdf2-worker.js @@ -12,13 +12,13 @@ */ self.onmessage = function(e) { - var args = e.data, + var i = e.data, key = null; - if (e.data.password && e.data.keySize) { + if (i.password && i.keySize) { // start deriving key var pbkdf2 = new app.crypto.PBKDF2(); - key = pbkdf2.getKey(e.data.password, e.data.keySize); + key = pbkdf2.getKey(i.password, i.keySize); } else { throw 'Not all arguments for web worker crypto are defined!'; diff --git a/src/js/crypto/util.js b/src/js/crypto/util.js index 975e460..e7a0025 100644 --- a/src/js/crypto/util.js +++ b/src/js/crypto/util.js @@ -59,6 +59,24 @@ var Util = function(window, uuid, crypt) { return outList; }; + this.encryptListForUser = function(aes, rsa, list) { + // encrypt list + var encryptedList = this.encryptList(aes, list); + + // encrypt keys for user + encryptedList.forEach(function(i) { + // process new values + i.itemIV = i.iv; + i.encryptedKey = rsa.encrypt(i.key); + i.keyIV = rsa.sign([i.itemIV, i.encryptedKey, i.ciphertext]); + // delete old ones + delete i.iv; + delete i.key; + }); + + return encryptedList; + }; + /** * Decrypt a list of items * @param aes [Object] The object implementing the aes mode @@ -80,6 +98,36 @@ var Util = function(window, uuid, crypt) { return outList; }; + this.decryptListForUser = function(aes, rsa, encryptedList) { + var list = [], + self = this; + + // decrypt keys for user + encryptedList.forEach(function(i) { + // verify signature + if (!rsa.verify([i.itemIV, i.encryptedKey, i.ciphertext], i.keyIV)) { + throw new Error('Verifying RSA signature failed!'); + } + // precoess new values + i.iv = i.itemIV; + i.key = rsa.decrypt(i.encryptedKey); + // delete old values + delete i.keyIV; + delete i.itemIV; + delete i.encryptedKey; + }); + + // decrypt list + var decryptedList = this.decryptList(aes, encryptedList); + + // add plaintext to list + decryptedList.forEach(function(i) { + list.push(i.plaintext); + }); + + return list; + }; + /** * Parse a date string with the following format "1900-01-31 18:17:53" */