From 03a60c254647d22fc9883502f1db0af9f074f808 Mon Sep 17 00:00:00 2001 From: Tankred Hase Date: Sat, 1 Jun 2013 10:58:50 +0200 Subject: [PATCH] integrated refactored item batch encryption --- src/js/crypto/crypto-batch.js | 123 ++++++++++++++++++---------------- test/unit/crypto-test.js | 21 ------ 2 files changed, 64 insertions(+), 80 deletions(-) diff --git a/src/js/crypto/crypto-batch.js b/src/js/crypto/crypto-batch.js index 6144829..c01cf97 100644 --- a/src/js/crypto/crypto-batch.js +++ b/src/js/crypto/crypto-batch.js @@ -7,31 +7,55 @@ var CryptoBatch = function(aes, rsa, util, _) { /** - * Encrypt a list of items using AES - * @param list [Array] The list of items to encrypt + * Encrypt and sign a an item using AES and RSA + * @param i [Object] The item to encrypt + * @param receiverPubkey [String] The public key used to encrypt + * @param senderKeyId [String] The sender's private key ID used to sign */ - this.encryptList = function(list) { - list.forEach(function(i) { - // stringify to JSON before encryption - i.ciphertext = aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv); - delete i.plaintext; - }); + this.encryptItemForUser = function(i, receiverPubkey, senderKeyId) { + // set rsa public key used to encrypt + rsa.init(receiverPubkey); - return list; + // stringify to JSON before symmetric encryption + i.ciphertext = aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv); + + // encrypt symmetric item key for user + i.encryptedKey = rsa.encrypt(i.key); + // set sender's keypair id for later verification + i.senderPk = senderKeyId; + // sign the bundle + i.signature = rsa.sign([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext]); + + // delete plaintext values + delete i.plaintext; + delete i.key; + delete i.receiverPk; }; /** - * Decrypt a list of items using AES - * @param list [Array] The list of items to decrypt + * Decrypt and verify an item using AES and RSA + * @param i [Object] The item to decrypt + * @param senderPubkey [String] A public key used to verify */ - this.decryptList = function(list) { - list.forEach(function(i) { - // decrypt JSON and parse to object literal - i.plaintext = JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv)); - delete i.ciphertext; - }); + this.decryptItemForUser = function(i, senderPubkey) { + // set rsa public key used to verify + rsa.init(senderPubkey); - return list; + // verify signature + if (!rsa.verify([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext], i.signature)) { + throw new Error('Verifying RSA signature failed!'); + } + // decrypt symmetric item key for user + i.key = rsa.decrypt(i.encryptedKey); + + // symmetrically decrypt JSON and parse to object literal + i.plaintext = JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv)); + + // delete ciphertext values + delete i.signature; + delete i.encryptedKey; + delete i.senderPk; + delete i.ciphertext; }; /** @@ -41,31 +65,24 @@ * @param senderPrivkey [Array] The sender's private key used to sign */ this.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) { - // encrypt list with aes - var encryptedList = this.encryptList(list); + var receiverPk, + self = this; // set sender private key rsa.init(null, senderPrivkey.privateKey); - // encrypt keys for user - encryptedList.forEach(function(i) { - // fetch correct public key - var pk = _.findWhere(receiverPubkeys, { + list.forEach(function(i) { + // fetch correct public key for encryption + receiverPk = null; + receiverPk = _.findWhere(receiverPubkeys, { _id: i.receiverPk }); - // set rsa public key used to encrypt - rsa.init(pk.publicKey); - // process new values - i.encryptedKey = rsa.encrypt(i.key); - i.senderPk = senderPrivkey._id; - i.signature = rsa.sign([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext]); - // delete old ones - delete i.key; - delete i.receiverPk; + // encrypt item for user + self.encryptItemForUser(i, receiverPk.publicKey, senderPrivkey._id); }); - return encryptedList; + return list; }; /** @@ -74,42 +91,30 @@ * @param senderPubkeys [Array] A list of public keys used to verify * @param receiverPrivkey [Array] The receiver's private key used to decrypt */ - this.decryptListForUser = function(encryptedList, senderPubkeys, receiverPrivkey) { - var j, self = this; + this.decryptListForUser = function(list, senderPubkeys, receiverPrivkey) { + var senderPk, j, + self = this; // set receiver private key rsa.init(null, receiverPrivkey.privateKey); - // decrypt keys for user - encryptedList.forEach(function(i) { - // fetch correct public key - var pk = _.findWhere(senderPubkeys, { + list.forEach(function(i) { + // fetch correct public key for verification + senderPk = null; + senderPk = _.findWhere(senderPubkeys, { _id: i.senderPk }); - // set rsa public key used to verify - rsa.init(pk.publicKey); - // verify signature - if (!rsa.verify([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext], i.signature)) { - throw new Error('Verifying RSA signature failed!'); - } - // process new values - i.key = rsa.decrypt(i.encryptedKey); - // delete old values - delete i.signature; - delete i.encryptedKey; - delete i.senderPk; + // decrypt item for user + self.decryptItemForUser(i, senderPk.publicKey); }); - // decrypt list - var decryptedList = this.decryptList(encryptedList); - - // add plaintext to list - for (j = 0; j < decryptedList.length; j++) { - decryptedList[j] = decryptedList[j].plaintext; + // set plaintext as list item + for (j = 0; j < list.length; j++) { + list[j] = list[j].plaintext; } - return decryptedList; + return list; }; }; diff --git a/test/unit/crypto-test.js b/test/unit/crypto-test.js index 489e423..7ef20b4 100644 --- a/test/unit/crypto-test.js +++ b/test/unit/crypto-test.js @@ -71,27 +71,6 @@ asyncTest("AES en/decrypt (Async/Worker)", 2, function() { }); }); -asyncTest("AES en/decrypt batch (Async/Worker)", 5, function() { - // generate test data - var collection, list, td = new TestData(); - - collection = td.getEmailCollection(100); - list = td.packageCollectionForEncryption(collection, crypto_test.keySize, crypto_test.ivSize); - - crypto_test.crypto.aesEncryptList(list, function(encryptedList) { - ok(encryptedList, 'Encrypt list'); - equal(encryptedList.length, list.length, 'Length of list'); - - crypto_test.crypto.aesDecryptList(encryptedList, function(decryptedList) { - ok(decryptedList, 'Decrypt list'); - equal(decryptedList.length, list.length, 'Length of list'); - deepEqual(decryptedList, list, 'Decrypted list is correct'); - - start(); - }); - }); -}); - asyncTest("AES/RSA encrypt batch for User (Async/Worker)", 2, function() { // generate test data var collection, td = new TestData();