integrated refactored item batch encryption

This commit is contained in:
Tankred Hase 2013-06-01 10:58:50 +02:00
parent b1b91850a7
commit 03a60c2546
2 changed files with 64 additions and 80 deletions

View File

@ -7,31 +7,55 @@
var CryptoBatch = function(aes, rsa, util, _) { var CryptoBatch = function(aes, rsa, util, _) {
/** /**
* Encrypt a list of items using AES * Encrypt and sign a an item using AES and RSA
* @param list [Array] The list of items to encrypt * @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) { this.encryptItemForUser = function(i, receiverPubkey, senderKeyId) {
list.forEach(function(i) { // set rsa public key used to encrypt
// stringify to JSON before encryption rsa.init(receiverPubkey);
i.ciphertext = aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv);
delete i.plaintext;
});
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 * Decrypt and verify an item using AES and RSA
* @param list [Array] The list of items to decrypt * @param i [Object] The item to decrypt
* @param senderPubkey [String] A public key used to verify
*/ */
this.decryptList = function(list) { this.decryptItemForUser = function(i, senderPubkey) {
list.forEach(function(i) { // set rsa public key used to verify
// decrypt JSON and parse to object literal rsa.init(senderPubkey);
i.plaintext = JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv));
delete i.ciphertext;
});
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 * @param senderPrivkey [Array] The sender's private key used to sign
*/ */
this.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) { this.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) {
// encrypt list with aes var receiverPk,
var encryptedList = this.encryptList(list); self = this;
// set sender private key // set sender private key
rsa.init(null, senderPrivkey.privateKey); rsa.init(null, senderPrivkey.privateKey);
// encrypt keys for user list.forEach(function(i) {
encryptedList.forEach(function(i) { // fetch correct public key for encryption
// fetch correct public key receiverPk = null;
var pk = _.findWhere(receiverPubkeys, { receiverPk = _.findWhere(receiverPubkeys, {
_id: i.receiverPk _id: i.receiverPk
}); });
// set rsa public key used to encrypt
rsa.init(pk.publicKey);
// process new values // encrypt item for user
i.encryptedKey = rsa.encrypt(i.key); self.encryptItemForUser(i, receiverPk.publicKey, senderPrivkey._id);
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;
}); });
return encryptedList; return list;
}; };
/** /**
@ -74,42 +91,30 @@
* @param senderPubkeys [Array] A list of public keys used to verify * @param senderPubkeys [Array] A list of public keys used to verify
* @param receiverPrivkey [Array] The receiver's private key used to decrypt * @param receiverPrivkey [Array] The receiver's private key used to decrypt
*/ */
this.decryptListForUser = function(encryptedList, senderPubkeys, receiverPrivkey) { this.decryptListForUser = function(list, senderPubkeys, receiverPrivkey) {
var j, self = this; var senderPk, j,
self = this;
// set receiver private key // set receiver private key
rsa.init(null, receiverPrivkey.privateKey); rsa.init(null, receiverPrivkey.privateKey);
// decrypt keys for user list.forEach(function(i) {
encryptedList.forEach(function(i) { // fetch correct public key for verification
// fetch correct public key senderPk = null;
var pk = _.findWhere(senderPubkeys, { senderPk = _.findWhere(senderPubkeys, {
_id: i.senderPk _id: i.senderPk
}); });
// set rsa public key used to verify
rsa.init(pk.publicKey);
// verify signature // decrypt item for user
if (!rsa.verify([i.iv, util.str2Base64(i.id), util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext], i.signature)) { self.decryptItemForUser(i, senderPk.publicKey);
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 list // set plaintext as list item
var decryptedList = this.decryptList(encryptedList); for (j = 0; j < list.length; j++) {
list[j] = list[j].plaintext;
// add plaintext to list
for (j = 0; j < decryptedList.length; j++) {
decryptedList[j] = decryptedList[j].plaintext;
} }
return decryptedList; return list;
}; };
}; };

View File

@ -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() { asyncTest("AES/RSA encrypt batch for User (Async/Worker)", 2, function() {
// generate test data // generate test data
var collection, td = new TestData(); var collection, td = new TestData();