mirror of
https://github.com/moparisthebest/mail
synced 2025-01-08 12:08:07 -05:00
add symmetric batch encryption to crypto, delete unnecessary crypto code
This commit is contained in:
parent
710fc7ea4a
commit
873671f011
@ -1,42 +0,0 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// import web worker dependencies
|
||||
importScripts('../../lib/require.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) {
|
||||
// fetch dependencies via require.js
|
||||
require(['../../require-config'], function() {
|
||||
require.config({
|
||||
baseUrl: '../../lib'
|
||||
});
|
||||
|
||||
require(['cryptoLib/crypto-batch'], function(batch) {
|
||||
|
||||
var i = e.data,
|
||||
output = null;
|
||||
|
||||
if (i.type === 'encrypt' && i.list) {
|
||||
// start encryption
|
||||
output = batch.encryptList(i.list);
|
||||
|
||||
} else if (i.type === 'decrypt' && i.list) {
|
||||
// start decryption
|
||||
output = batch.decryptList(i.list);
|
||||
|
||||
} else {
|
||||
throw 'Not all arguments for web worker crypto are defined!';
|
||||
}
|
||||
|
||||
// pass output back to main thread
|
||||
self.postMessage(output);
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
@ -64,7 +64,7 @@
|
||||
var self = this;
|
||||
|
||||
// validate args
|
||||
if (!parts || !key) {
|
||||
if (!parts || parts.length < 1 || !key) {
|
||||
throw new Error("Missing args for hmac processing!");
|
||||
}
|
||||
|
||||
|
@ -1,42 +0,0 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// import web worker dependencies
|
||||
importScripts('../../lib/require.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) {
|
||||
// fetch dependencies via require.js
|
||||
require(['../../require-config'], function() {
|
||||
require.config({
|
||||
baseUrl: '../../lib'
|
||||
});
|
||||
|
||||
require(['cryptoLib/aes-cbc'], function(aes) {
|
||||
|
||||
var i = e.data,
|
||||
output = null;
|
||||
|
||||
if (i.type === 'encrypt' && i.plaintext && i.key && i.iv) {
|
||||
// start encryption
|
||||
output = aes.encrypt(i.plaintext, i.key, i.iv);
|
||||
|
||||
} else if (i.type === 'decrypt' && i.ciphertext && i.key && i.iv) {
|
||||
// start decryption
|
||||
output = aes.decrypt(i.ciphertext, i.key, i.iv);
|
||||
|
||||
} else {
|
||||
throw 'Not all arguments for web worker crypto are defined!';
|
||||
}
|
||||
|
||||
// pass output back to main thread
|
||||
self.postMessage(output);
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
}());
|
@ -39,23 +39,47 @@
|
||||
function doOperation(batch, i) {
|
||||
var output;
|
||||
|
||||
if (i.type === 'encrypt' && i.receiverPubkeys && i.senderPrivkey && i.list) {
|
||||
//
|
||||
// Asymmetric encryption
|
||||
//
|
||||
|
||||
if (i.type === 'asymEncrypt' && i.receiverPubkeys && i.senderPrivkey && i.list) {
|
||||
// start encryption
|
||||
output = batch.encryptListForUser(i.list, i.receiverPubkeys, i.senderPrivkey);
|
||||
|
||||
} else if (i.type === 'decrypt' && i.senderPubkeys && i.receiverPrivkey && i.list) {
|
||||
} else if (i.type === 'asymDecrypt' && i.senderPubkeys && i.receiverPrivkey && i.list) {
|
||||
// start decryption
|
||||
output = batch.decryptListForUser(i.list, i.senderPubkeys, i.receiverPrivkey);
|
||||
}
|
||||
|
||||
} else if (i.type === 'reencrypt' && i.senderPubkeys && i.receiverPrivkey && i.list && i.symKey) {
|
||||
//
|
||||
// Symmetric encryption
|
||||
//
|
||||
else if (i.type === 'symEncrypt' && i.list) {
|
||||
// start encryption
|
||||
output = batch.authEncryptList(i.list);
|
||||
|
||||
} else if (i.type === 'symDecrypt' && i.list && i.keys) {
|
||||
// start decryption
|
||||
output = batch.authDecryptList(i.list, i.keys);
|
||||
}
|
||||
|
||||
//
|
||||
// Reencryption of asymmetric items to symmetric items
|
||||
//
|
||||
else if (i.type === 'reencrypt' && i.senderPubkeys && i.receiverPrivkey && i.list && i.symKey) {
|
||||
// start validation and re-encryption
|
||||
output = batch.reencryptListKeysForUser(i.list, i.senderPubkeys, i.receiverPrivkey, i.symKey);
|
||||
|
||||
} else if (i.type === 'decryptItems' && i.symKey && i.list) {
|
||||
// start decryption
|
||||
output = batch.decryptKeysAndList(i.list, i.symKey);
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// Error
|
||||
//
|
||||
else {
|
||||
output = {
|
||||
err: {
|
||||
errMsg: 'Not all arguments for web worker crypto are defined!'
|
||||
|
@ -1,248 +1,341 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Crypto batch library for processing large sets of data
|
||||
*/
|
||||
var CryptoBatch = function(aes, rsa, util, _) {
|
||||
/**
|
||||
* Crypto batch library for processing large sets of data
|
||||
*/
|
||||
var CryptoBatch = function(aes, rsa, util, _) {
|
||||
this._aes = aes;
|
||||
this._rsa = rsa;
|
||||
this._util = util;
|
||||
this.__ = _;
|
||||
};
|
||||
|
||||
//
|
||||
// Encrypt batch
|
||||
//
|
||||
//
|
||||
// Encrypt batch for user AES/RSA
|
||||
//
|
||||
|
||||
/**
|
||||
* Encrypt and sign 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.encryptItemForUser = function(i, receiverPubkey, senderKeyId) {
|
||||
// set rsa public key used to encrypt
|
||||
rsa.init(receiverPubkey);
|
||||
/**
|
||||
* Encrypt and sign a list of items using AES and RSA
|
||||
* @param list [Array] The list of items to encrypt
|
||||
* @param receiverPubkeys [Array] A list of public keys used to encrypt
|
||||
* @param senderPrivkey [Array] The sender's private key used to sign
|
||||
*/
|
||||
CryptoBatch.prototype.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) {
|
||||
var receiverPk,
|
||||
self = this;
|
||||
|
||||
// stringify to JSON before symmetric encryption
|
||||
i.ciphertext = aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv);
|
||||
// encrypt a list of items
|
||||
self.encryptList(list);
|
||||
|
||||
// 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.senderPk), i.encryptedKey, i.ciphertext]);
|
||||
// set sender private key
|
||||
self._rsa.init(null, senderPrivkey.privateKey);
|
||||
|
||||
// delete plaintext values
|
||||
delete i.plaintext;
|
||||
delete i.key;
|
||||
delete i.receiverPk;
|
||||
list.forEach(function(i) {
|
||||
// fetch correct public key for encryption
|
||||
receiverPk = null;
|
||||
receiverPk = self.__.findWhere(receiverPubkeys, {
|
||||
_id: i.receiverPk
|
||||
});
|
||||
|
||||
return i;
|
||||
};
|
||||
// encrypt item for user
|
||||
self.encryptItemKeyForUser(i, receiverPk.publicKey, senderPrivkey._id);
|
||||
});
|
||||
|
||||
/**
|
||||
* Encrypt and sign a list of items using AES and RSA
|
||||
* @param list [Array] The list of items to encrypt
|
||||
* @param receiverPubkeys [Array] A list of public keys used to encrypt
|
||||
* @param senderPrivkey [Array] The sender's private key used to sign
|
||||
*/
|
||||
this.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) {
|
||||
var receiverPk,
|
||||
self = this;
|
||||
return list;
|
||||
};
|
||||
|
||||
// set sender private key
|
||||
rsa.init(null, senderPrivkey.privateKey);
|
||||
/**
|
||||
* Encrypt and sign 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
|
||||
*/
|
||||
CryptoBatch.prototype.encryptItemKeyForUser = function(i, receiverPubkey, senderKeyId) {
|
||||
var self = this;
|
||||
|
||||
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
|
||||
self._rsa.init(receiverPubkey);
|
||||
// encrypt symmetric item key for user
|
||||
i.encryptedKey = self._rsa.encrypt(i.key);
|
||||
// set sender's keypair id for later verification
|
||||
i.senderPk = senderKeyId;
|
||||
// sign the bundle
|
||||
i.signature = self._rsa.sign([i.iv, self._util.str2Base64(i.senderPk), i.encryptedKey, i.ciphertext]);
|
||||
|
||||
// encrypt item for user
|
||||
self.encryptItemForUser(i, receiverPk.publicKey, senderPrivkey._id);
|
||||
});
|
||||
// delete plaintext values
|
||||
delete i.key;
|
||||
delete i.receiverPk;
|
||||
|
||||
return list;
|
||||
};
|
||||
return i;
|
||||
};
|
||||
|
||||
//
|
||||
// Decrypt batch
|
||||
//
|
||||
//
|
||||
// Decrypt batch for user AES/RSA
|
||||
//
|
||||
|
||||
/**
|
||||
* Verfiy an item and decrypt its item key using RSA
|
||||
* @param i [Object] The item to decrypt
|
||||
* @param senderPubkey [String] A public key used to verify
|
||||
*/
|
||||
this.decryptItemKeyForUser = function(i, senderPubkey) {
|
||||
// set rsa public key used to verify
|
||||
rsa.init(senderPubkey);
|
||||
/**
|
||||
* Decrypt and verify a list of items using AES and RSA
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param senderPubkeys [Array] A list of public keys used to verify
|
||||
* @param receiverPrivkey [Array] The receiver's private key used to decrypt
|
||||
*/
|
||||
CryptoBatch.prototype.decryptListForUser = function(list, senderPubkeys, receiverPrivkey) {
|
||||
var j;
|
||||
|
||||
// verify signature
|
||||
if (!rsa.verify([i.iv, 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);
|
||||
// verify and decrypt a list of items using RSA
|
||||
this.decryptListKeysForUser(list, senderPubkeys, receiverPrivkey);
|
||||
|
||||
// delete ciphertext values
|
||||
delete i.signature;
|
||||
delete i.encryptedKey;
|
||||
delete i.senderPk;
|
||||
// decrypt a list of items
|
||||
this.decryptList(list);
|
||||
|
||||
return i;
|
||||
};
|
||||
// set plaintext as list item
|
||||
for (j = 0; j < list.length; j++) {
|
||||
list[j] = list[j].plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt and verify a list of item keys using RSA
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param senderPubkeys [Array] A list of public keys used to verify
|
||||
* @param receiverPrivkey [String] The receiver's private key used to decrypt
|
||||
*/
|
||||
this.decryptListKeysForUser = function(list, senderPubkeys, receiverPrivkey) {
|
||||
var senderPk,
|
||||
self = this;
|
||||
return list;
|
||||
};
|
||||
|
||||
// set receiver private key
|
||||
rsa.init(null, receiverPrivkey.privateKey);
|
||||
/**
|
||||
* Decrypt and verify a list of item keys using RSA
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param senderPubkeys [Array] A list of public keys used to verify
|
||||
* @param receiverPrivkey [String] The receiver's private key used to decrypt
|
||||
*/
|
||||
CryptoBatch.prototype.decryptListKeysForUser = function(list, senderPubkeys, receiverPrivkey) {
|
||||
var self = this,
|
||||
senderPk;
|
||||
|
||||
list.forEach(function(i) {
|
||||
// fetch correct public key for verification
|
||||
senderPk = null;
|
||||
senderPk = _.findWhere(senderPubkeys, {
|
||||
_id: i.senderPk
|
||||
});
|
||||
// set receiver private key
|
||||
self._rsa.init(null, receiverPrivkey.privateKey);
|
||||
|
||||
// decrypt item for user
|
||||
self.decryptItemKeyForUser(i, senderPk.publicKey);
|
||||
});
|
||||
list.forEach(function(i) {
|
||||
// fetch correct public key for verification
|
||||
senderPk = null;
|
||||
senderPk = self.__.findWhere(senderPubkeys, {
|
||||
_id: i.senderPk
|
||||
});
|
||||
|
||||
return list;
|
||||
};
|
||||
// decrypt item for user
|
||||
self.decryptItemKeyForUser(i, senderPk.publicKey);
|
||||
});
|
||||
|
||||
/**
|
||||
* Decrypt a list of item keys using RSA and the encrypt them again using AES
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param senderPubkeys [Array] A list of public keys used to verify
|
||||
* @param receiverPrivkey [String] The receiver's private key used to decrypt
|
||||
* @param symKey [String] The symmetric key used to re-encrypt the item key
|
||||
*/
|
||||
this.reencryptListKeysForUser = function(list, senderPubkeys, receiverPrivkey, symKey) {
|
||||
// verify and decrypt item keys using RSA
|
||||
this.decryptListKeysForUser(list, senderPubkeys, receiverPrivkey);
|
||||
return list;
|
||||
};
|
||||
|
||||
list.forEach(function(i) {
|
||||
// re-encrypt item key using aes
|
||||
i.encryptedKey = aes.encrypt(i.key, symKey, i.iv);
|
||||
/**
|
||||
* Verfiy an item and decrypt its item key using RSA
|
||||
* @param i [Object] The item to decrypt
|
||||
* @param senderPubkey [String] A public key used to verify
|
||||
*/
|
||||
CryptoBatch.prototype.decryptItemKeyForUser = function(i, senderPubkey) {
|
||||
var self = this;
|
||||
|
||||
delete i.key;
|
||||
});
|
||||
// set rsa public key used to verify
|
||||
self._rsa.init(senderPubkey);
|
||||
|
||||
return list;
|
||||
};
|
||||
// verify signature
|
||||
if (!self._rsa.verify([i.iv, self._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 = self._rsa.decrypt(i.encryptedKey);
|
||||
|
||||
/**
|
||||
* Decrypt an item using AES
|
||||
* @param i [Object] The item to decrypt
|
||||
*/
|
||||
this.decryptItem = function(i) {
|
||||
// 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 ciphertext values
|
||||
delete i.ciphertext;
|
||||
return i;
|
||||
};
|
||||
|
||||
return i;
|
||||
};
|
||||
//
|
||||
// Encrypt batch AES
|
||||
//
|
||||
|
||||
/**
|
||||
* Decrypt a list of items using AES
|
||||
* @param i [Object] The item to decrypt
|
||||
*/
|
||||
this.decryptList = function(list) {
|
||||
var self = this;
|
||||
/**
|
||||
* Encrypt an item using AES
|
||||
* @param i [Object] The item to encrypt
|
||||
*/
|
||||
CryptoBatch.prototype.encryptItem = function(i) {
|
||||
var self = this;
|
||||
|
||||
list.forEach(function(i) {
|
||||
// decrypt item for user
|
||||
self.decryptItem(i);
|
||||
});
|
||||
// stringify to JSON before symmetric encryption
|
||||
i.ciphertext = self._aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv);
|
||||
|
||||
return list;
|
||||
};
|
||||
// delete plaintext values
|
||||
delete i.plaintext;
|
||||
|
||||
/**
|
||||
* Decrypt keys and items using AES
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param symKey [String] The symmetric key used to re-encrypt the item key
|
||||
*/
|
||||
this.decryptKeysAndList = function(list, symKey) {
|
||||
var self = this,
|
||||
j;
|
||||
return i;
|
||||
};
|
||||
|
||||
list.forEach(function(i) {
|
||||
// decrypt item key
|
||||
i.key = aes.decrypt(i.encryptedKey, symKey, i.iv);
|
||||
// decrypt item for user
|
||||
self.decryptItem(i);
|
||||
/**
|
||||
* Encrypt a list of items using AES
|
||||
* @param i [Object] The item to encrypt
|
||||
*/
|
||||
CryptoBatch.prototype.encryptList = function(list) {
|
||||
var self = this;
|
||||
|
||||
delete i.encryptedKey;
|
||||
});
|
||||
list.forEach(function(i) {
|
||||
// encrypt item
|
||||
self.encryptItem(i);
|
||||
});
|
||||
|
||||
// set plaintext as list item
|
||||
for (j = 0; j < list.length; j++) {
|
||||
list[j] = list[j].plaintext;
|
||||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
return list;
|
||||
};
|
||||
/**
|
||||
* Encrypt a list of items using AES and hash using HMAC
|
||||
* @param i [Object] The item to encrypt
|
||||
*/
|
||||
CryptoBatch.prototype.authEncryptList = function(list) {
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* 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.decryptItemForUser = function(i, senderPubkey) {
|
||||
// verfiy signature and decrypt item key
|
||||
this.decryptItemKeyForUser(i, senderPubkey);
|
||||
self.encryptList(list);
|
||||
|
||||
// symmetrically decrypt JSON and parse to object literal
|
||||
this.decryptItem(i);
|
||||
list.forEach(function(i) {
|
||||
// calculate hmac of iv and ciphertext using key
|
||||
i.hmac = self._aes.hmac([i.iv, i.ciphertext], i.key);
|
||||
|
||||
return i;
|
||||
};
|
||||
// delete symmetric key on each item
|
||||
delete i.key;
|
||||
});
|
||||
|
||||
/**
|
||||
* Decrypt and verify a list of items using AES and RSA
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @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(list, senderPubkeys, receiverPrivkey) {
|
||||
var j;
|
||||
return list;
|
||||
};
|
||||
|
||||
// verify and decrypt a list of items using RSA
|
||||
this.decryptListKeysForUser(list, senderPubkeys, receiverPrivkey);
|
||||
//
|
||||
// Decrypt batch AES
|
||||
//
|
||||
|
||||
// decrypt a list of items
|
||||
this.decryptList(list);
|
||||
/**
|
||||
* Decrypt an item using AES
|
||||
* @param i [Object] The item to decrypt
|
||||
*/
|
||||
CryptoBatch.prototype.decryptItem = function(i) {
|
||||
var self = this;
|
||||
|
||||
// set plaintext as list item
|
||||
for (j = 0; j < list.length; j++) {
|
||||
list[j] = list[j].plaintext;
|
||||
}
|
||||
// symmetrically decrypt JSON and parse to object literal
|
||||
i.plaintext = JSON.parse(self._aes.decrypt(i.ciphertext, i.key, i.iv));
|
||||
|
||||
return list;
|
||||
};
|
||||
};
|
||||
// delete ciphertext values
|
||||
delete i.ciphertext;
|
||||
|
||||
if (typeof define !== 'undefined' && define.amd) {
|
||||
// AMD
|
||||
define(['cryptoLib/aes-cbc', 'cryptoLib/rsa', 'cryptoLib/util', 'underscore'], function(aes, rsa, util, _) {
|
||||
return new CryptoBatch(aes, rsa, util, _);
|
||||
});
|
||||
} else if (typeof module !== 'undefined' && module.exports) {
|
||||
// node.js
|
||||
module.exports = new CryptoBatch(require('./aes-cbc'), require('./rsa'), require('./util'), require('underscore'));
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt a list of items using AES
|
||||
* @param i [Object] The item to decrypt
|
||||
*/
|
||||
CryptoBatch.prototype.decryptList = function(list) {
|
||||
var self = this;
|
||||
|
||||
list.forEach(function(i) {
|
||||
// decrypt item
|
||||
self.decryptItem(i);
|
||||
});
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encrypt a list of items using AES and verfiy using HMAC
|
||||
* @param i [Object] The item to decrypt
|
||||
*/
|
||||
CryptoBatch.prototype.authDecryptList = function(list, keys) {
|
||||
var self = this,
|
||||
i, len, calculated, j;
|
||||
|
||||
for (i = 0, len = list.length; i < len; i++) {
|
||||
// validate presence of args
|
||||
if (!list[i].hmac || !list[i].iv || !list[i].ciphertext || !keys[i]) {
|
||||
throw new Error('Arguments for hmac verification missing!');
|
||||
}
|
||||
|
||||
// verify hmac of each item
|
||||
calculated = self._aes.hmac([list[i].iv, list[i].ciphertext], keys[i]);
|
||||
if (list[i].hmac !== calculated) {
|
||||
throw new Error('Hmac verification failed!');
|
||||
}
|
||||
|
||||
// set key property for batch decryption
|
||||
list[i].key = keys[i];
|
||||
}
|
||||
|
||||
// decrypt lsit using aes
|
||||
self.decryptList(list);
|
||||
|
||||
// set plaintext as list item
|
||||
for (j = 0; j < list.length; j++) {
|
||||
list[j] = list[j].plaintext;
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
//
|
||||
// Reencrypt batch for user AES/RSA
|
||||
//
|
||||
|
||||
/**
|
||||
* Decrypt a list of item keys using RSA and the encrypt them again using AES
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param senderPubkeys [Array] A list of public keys used to verify
|
||||
* @param receiverPrivkey [String] The receiver's private key used to decrypt
|
||||
* @param symKey [String] The symmetric key used to re-encrypt the item key
|
||||
*/
|
||||
CryptoBatch.prototype.reencryptListKeysForUser = function(list, senderPubkeys, receiverPrivkey, symKey) {
|
||||
var self = this;
|
||||
|
||||
// verify and decrypt item keys using RSA
|
||||
this.decryptListKeysForUser(list, senderPubkeys, receiverPrivkey);
|
||||
|
||||
list.forEach(function(i) {
|
||||
// re-encrypt item key using aes
|
||||
i.encryptedKey = self._aes.encrypt(i.key, symKey, i.iv);
|
||||
|
||||
delete i.key;
|
||||
});
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Decrypt keys and items using AES
|
||||
* @param list [Array] The list of items to decrypt
|
||||
* @param symKey [String] The symmetric key used to re-encrypt the item key
|
||||
*/
|
||||
CryptoBatch.prototype.decryptKeysAndList = function(list, symKey) {
|
||||
var self = this,
|
||||
j;
|
||||
|
||||
list.forEach(function(i) {
|
||||
// decrypt item key
|
||||
i.key = self._aes.decrypt(i.encryptedKey, symKey, i.iv);
|
||||
// decrypt item for user
|
||||
self.decryptItem(i);
|
||||
|
||||
delete i.encryptedKey;
|
||||
});
|
||||
|
||||
// set plaintext as list item
|
||||
for (j = 0; j < list.length; j++) {
|
||||
list[j] = list[j].plaintext;
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
if (typeof define !== 'undefined' && define.amd) {
|
||||
// AMD
|
||||
define(['cryptoLib/aes-cbc', 'cryptoLib/rsa', 'cryptoLib/util', 'underscore'], function(aes, rsa, util, _) {
|
||||
return new CryptoBatch(aes, rsa, util, _);
|
||||
});
|
||||
} else if (typeof module !== 'undefined' && module.exports) {
|
||||
// node.js
|
||||
module.exports = new CryptoBatch(require('./aes-cbc'), require('./rsa'), require('./util'), require('underscore'));
|
||||
}
|
||||
|
||||
})();
|
@ -126,59 +126,48 @@ define(function(require) {
|
||||
});
|
||||
};
|
||||
|
||||
//
|
||||
// En/Decrypts single item
|
||||
//
|
||||
|
||||
self.aesEncrypt = function(plaintext, key, iv, callback) {
|
||||
startWorker('/crypto/aes-worker.js', {
|
||||
type: 'encrypt',
|
||||
plaintext: plaintext,
|
||||
key: key,
|
||||
iv: iv
|
||||
}, callback, function() {
|
||||
return self.aesEncryptSync(plaintext, key, iv);
|
||||
});
|
||||
};
|
||||
|
||||
self.aesDecrypt = function(ciphertext, key, iv, callback) {
|
||||
startWorker('/crypto/aes-worker.js', {
|
||||
type: 'decrypt',
|
||||
ciphertext: ciphertext,
|
||||
key: key,
|
||||
iv: iv
|
||||
}, callback, function() {
|
||||
return self.aesDecryptSync(ciphertext, key, iv);
|
||||
});
|
||||
};
|
||||
|
||||
self.aesEncryptSync = function(plaintext, key, iv) {
|
||||
return aes.encrypt(plaintext, key, iv);
|
||||
};
|
||||
|
||||
self.aesDecryptSync = function(ciphertext, key, iv) {
|
||||
return aes.decrypt(ciphertext, key, iv);
|
||||
};
|
||||
|
||||
//
|
||||
// En/Decrypt a list of items with AES in a WebWorker thread
|
||||
//
|
||||
|
||||
self.aesEncryptList = function(list, callback) {
|
||||
startWorker('/crypto/aes-batch-worker.js', {
|
||||
type: 'encrypt',
|
||||
list: list
|
||||
}, callback, function() {
|
||||
return cryptoBatch.encryptList(list);
|
||||
self.symEncryptList = function(list, callback) {
|
||||
var key, envelope, envelopes = [];
|
||||
|
||||
// generate single secret key shared for all list items
|
||||
key = util.random(self.keySize);
|
||||
|
||||
// package objects into batchable envelope format
|
||||
list.forEach(function(i) {
|
||||
envelope = {
|
||||
id: i.id,
|
||||
plaintext: i,
|
||||
key: key,
|
||||
iv: util.random(self.ivSize)
|
||||
};
|
||||
envelopes.push(envelope);
|
||||
});
|
||||
|
||||
startWorker('/crypto/crypto-batch-worker.js', {
|
||||
type: 'symEncrypt',
|
||||
list: envelopes
|
||||
}, function(err, encryptedList) {
|
||||
// return generated secret key
|
||||
callback(err, {
|
||||
key: key,
|
||||
list: encryptedList
|
||||
});
|
||||
}, function() {
|
||||
return cryptoBatch.authEncryptList(envelopes);
|
||||
});
|
||||
};
|
||||
|
||||
self.aesDecryptList = function(list, callback) {
|
||||
startWorker('/crypto/aes-batch-worker.js', {
|
||||
type: 'decrypt',
|
||||
list: list
|
||||
self.symDecryptList = function(list, keys, callback) {
|
||||
startWorker('/crypto/crypto-batch-worker.js', {
|
||||
type: 'symDecrypt',
|
||||
list: list,
|
||||
keys: keys
|
||||
}, callback, function() {
|
||||
return cryptoBatch.decryptList(list);
|
||||
return cryptoBatch.authDecryptList(list, keys);
|
||||
});
|
||||
};
|
||||
|
||||
@ -215,7 +204,7 @@ define(function(require) {
|
||||
});
|
||||
|
||||
startWorker('/crypto/crypto-batch-worker.js', {
|
||||
type: 'encrypt',
|
||||
type: 'asymEncrypt',
|
||||
list: envelopes,
|
||||
senderPrivkey: senderPrivkey,
|
||||
receiverPubkeys: receiverPubkeys
|
||||
@ -239,7 +228,7 @@ define(function(require) {
|
||||
};
|
||||
|
||||
startWorker('/crypto/crypto-batch-worker.js', {
|
||||
type: 'decrypt',
|
||||
type: 'asymDecrypt',
|
||||
list: list,
|
||||
receiverPrivkey: receiverPrivkey,
|
||||
senderPubkeys: senderPubkeys
|
||||
|
@ -56,22 +56,34 @@ define(['js/crypto/crypto', 'cryptoLib/util', 'test/test-data'], function(crypto
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("AES en/decrypt (Async/Worker)", 4, function() {
|
||||
var secret = 'Big secret';
|
||||
asyncTest("AES/HMAC encrypt batch (Async/Worker)", 2, function() {
|
||||
// generate test data
|
||||
var collection;
|
||||
|
||||
var key = util.random(cryptoTest.keySize);
|
||||
var iv = util.random(cryptoTest.ivSize);
|
||||
collection = testData.getEmailCollection(10);
|
||||
cryptoTest.symlist = collection.toJSON();
|
||||
|
||||
crypto.aesEncrypt(secret, key, iv, function(err, ciphertext) {
|
||||
ok(!err);
|
||||
ok(ciphertext, 'Encrypt item');
|
||||
crypto.symEncryptList(cryptoTest.symlist, function(err, result) {
|
||||
ok(!err && result.key && result.list && result.list[0].hmac, 'Encrypt list for user');
|
||||
equal(result.list.length, cryptoTest.symlist.length, 'Length of list');
|
||||
cryptoTest.symEncryptedList = result.list;
|
||||
cryptoTest.symKey = result.key;
|
||||
|
||||
crypto.aesDecrypt(ciphertext, key, iv, function(err, decrypted) {
|
||||
ok(!err);
|
||||
equal(decrypted, secret, 'Decrypt item');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
start();
|
||||
});
|
||||
asyncTest("AES/HMAC decrypt batch (Async/Worker)", 3, function() {
|
||||
var keys = [];
|
||||
for (var i = 0; i < cryptoTest.symEncryptedList.length; i++) {
|
||||
keys.push(cryptoTest.symKey);
|
||||
}
|
||||
crypto.symDecryptList(cryptoTest.symEncryptedList, keys, function(err, decryptedList) {
|
||||
ok(!err && decryptedList, 'Decrypt list');
|
||||
equal(decryptedList.length, cryptoTest.symlist.length, 'Length of list');
|
||||
deepEqual(decryptedList, cryptoTest.symlist, 'Decrypted list is correct');
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -19,15 +19,18 @@ require(['../../src/require-config'], function() {
|
||||
});
|
||||
|
||||
function startTests() {
|
||||
require(['test/unit/forge-test',
|
||||
'test/unit/aes-test',
|
||||
'test/unit/rsa-test',
|
||||
'test/unit/lawnchair-dao-test',
|
||||
'test/unit/keychain-dao-test',
|
||||
'test/unit/crypto-test',
|
||||
'test/unit/devicestorage-dao-test'
|
||||
], function() {
|
||||
//Tests loaded, run tests
|
||||
QUnit.start();
|
||||
});
|
||||
require(
|
||||
[
|
||||
'test/unit/forge-test',
|
||||
'test/unit/aes-test',
|
||||
'test/unit/rsa-test',
|
||||
'test/unit/lawnchair-dao-test',
|
||||
'test/unit/keychain-dao-test',
|
||||
'test/unit/crypto-test',
|
||||
'test/unit/devicestorage-dao-test'
|
||||
], function() {
|
||||
//Tests loaded, run tests
|
||||
QUnit.start();
|
||||
}
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user