mirror of
https://github.com/moparisthebest/mail
synced 2024-11-25 18:32:20 -05:00
integrated new crypto lib api into crypto.js
This commit is contained in:
parent
52fba1a462
commit
1e27297013
@ -2,6 +2,7 @@
|
||||
'use strict';
|
||||
|
||||
// import web worker dependencies
|
||||
importScripts('../../lib/underscore-1.4.4.min.js');
|
||||
importScripts('../../lib/forge/forge.rsa.bundle.js');
|
||||
importScripts('../app-config.js');
|
||||
importScripts('./crypto-batch.js');
|
||||
@ -20,18 +21,15 @@
|
||||
aes = new cryptoLib.AesCBC(forge),
|
||||
rsa = new cryptoLib.RSA(forge),
|
||||
util = new cryptoLib.Util(),
|
||||
batch = new cryptoLib.CryptoBatch(aes, rsa, util);
|
||||
batch = new cryptoLib.CryptoBatch(aes, rsa, util, _);
|
||||
|
||||
// pass RSA keys to module
|
||||
rsa.init(i.pubkeyPem, i.privkeyPem);
|
||||
|
||||
if (i.type === 'encrypt' && i.list) {
|
||||
if (i.type === 'encrypt' && i.receiverPubkeys && i.senderPrivkey && i.list) {
|
||||
// start encryption
|
||||
output = batch.encryptListForUser(i.list);
|
||||
output = batch.encryptListForUser(i.list, i.receiverPubkeys, i.senderPrivkey);
|
||||
|
||||
} else if (i.type === 'decrypt' && i.list) {
|
||||
} else if (i.type === 'decrypt' && i.senderPubkeys && i.receiverPrivkey && i.list) {
|
||||
// start decryption
|
||||
output = batch.decryptListForUser(i.list);
|
||||
output = batch.decryptListForUser(i.list, i.senderPubkeys, i.receiverPrivkey);
|
||||
|
||||
} else {
|
||||
throw 'Not all arguments for web worker crypto are defined!';
|
||||
|
@ -4,11 +4,11 @@
|
||||
/**
|
||||
* Crypto batch library for processing large sets of data
|
||||
*/
|
||||
var CryptoBatch = function(aes, rsa, util) {
|
||||
var CryptoBatch = function(aes, rsa, util, _) {
|
||||
|
||||
/**
|
||||
* Encrypt a list of items using AES
|
||||
* @list list [Array] The list of items to encrypt
|
||||
* @param list [Array] The list of items to encrypt
|
||||
*/
|
||||
this.encryptList = function(list) {
|
||||
list.forEach(function(i) {
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
/**
|
||||
* Decrypt a list of items using AES
|
||||
* @list list [Array] The list of items to decrypt
|
||||
* @param list [Array] The list of items to decrypt
|
||||
*/
|
||||
this.decryptList = function(list) {
|
||||
list.forEach(function(i) {
|
||||
@ -36,19 +36,33 @@
|
||||
|
||||
/**
|
||||
* Encrypt and sign a list of items using AES and RSA
|
||||
* @list list [Array] The list of items to encrypt
|
||||
* @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) {
|
||||
// encrypt list
|
||||
this.encryptListForUser = function(list, receiverPubkeys, senderPrivkey) {
|
||||
// encrypt list with aes
|
||||
var encryptedList = this.encryptList(list);
|
||||
|
||||
// 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, {
|
||||
_id: i.receiverPk
|
||||
});
|
||||
// set rsa public key used to encrypt
|
||||
rsa.init(pk.publicKey);
|
||||
|
||||
// process new values
|
||||
i.encryptedKey = rsa.encrypt(i.key);
|
||||
i.signature = rsa.sign([i.iv, util.str2Base64(i.id), i.encryptedKey, i.ciphertext]);
|
||||
i.senderPk = senderPrivkey._id;
|
||||
// delete old ones
|
||||
delete i.key;
|
||||
delete i.receiverPk;
|
||||
});
|
||||
|
||||
return encryptedList;
|
||||
@ -56,22 +70,35 @@
|
||||
|
||||
/**
|
||||
* Decrypt and verify a list of items using AES and RSA
|
||||
* @list list [Array] The list of items to decrypt
|
||||
* @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(encryptedList) {
|
||||
this.decryptListForUser = function(encryptedList, senderPubkeys, receiverPrivkey) {
|
||||
var 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, {
|
||||
_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), i.encryptedKey, i.ciphertext], i.signature)) {
|
||||
throw new Error('Verifying RSA signature failed!');
|
||||
}
|
||||
// precoess new values
|
||||
// process new values
|
||||
i.key = rsa.decrypt(i.encryptedKey);
|
||||
// delete old values
|
||||
delete i.signature;
|
||||
delete i.encryptedKey;
|
||||
delete i.senderPk;
|
||||
});
|
||||
|
||||
// decrypt list
|
||||
|
@ -96,6 +96,8 @@ app.crypto.Crypto = function(window, util) {
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: not required since key is synced before crypto init in keychain dao getUserKeyPair
|
||||
|
||||
/**
|
||||
* Return a Public Key object containing the Public Key PEM
|
||||
*/
|
||||
@ -109,6 +111,8 @@ app.crypto.Crypto = function(window, util) {
|
||||
};
|
||||
};
|
||||
|
||||
// TODO: not required since key is synced before crypto init in keychain dao getUserKeyPair
|
||||
|
||||
/**
|
||||
* Return a Private Key object containing the encrypted private key
|
||||
*/
|
||||
@ -123,6 +127,8 @@ app.crypto.Crypto = function(window, util) {
|
||||
return storedKeypair;
|
||||
};
|
||||
|
||||
// TODO: not required since key is synced before crypto init in keychain dao getUserKeyPair
|
||||
|
||||
this.putEncryptedPrivateKey = function(privkey) {
|
||||
var strgId = (storageId) ? storageId : privkey.userId + '_encryptedKeypair';
|
||||
|
||||
@ -261,25 +267,37 @@ app.crypto.Crypto = function(window, util) {
|
||||
// En/Decrypt something speficially using the user's secret key
|
||||
//
|
||||
|
||||
this.encryptListForUser = function(list, recipientPubkey, callback) {
|
||||
this.encryptListForUser = function(list, receiverPubkeys, callback) {
|
||||
var envelope, envelopes = [],
|
||||
self = this;
|
||||
|
||||
if (!receiverPubkeys || receiverPubkeys.length !== 1) {
|
||||
callback({
|
||||
errMsg: 'Encryption is currently implemented for only one receiver!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var keypair = rsa.exportKeys();
|
||||
var senderPrivkey = {
|
||||
_id: keypair._id,
|
||||
privateKey: keypair.privkeyPem
|
||||
};
|
||||
|
||||
// package objects into batchable envelope format
|
||||
list.forEach(function(i) {
|
||||
envelope = {
|
||||
id: i.id,
|
||||
plaintext: i,
|
||||
key: util.random(self.keySize),
|
||||
iv: util.random(self.ivSize)
|
||||
iv: util.random(self.ivSize),
|
||||
receiverPk: receiverPubkeys[0]._id
|
||||
};
|
||||
envelopes.push(envelope);
|
||||
});
|
||||
|
||||
if (window.Worker) {
|
||||
|
||||
var keypair = rsa.exportKeys();
|
||||
|
||||
var worker = new Worker(app.config.workerPath + '/crypto/crypto-batch-worker.js');
|
||||
worker.onmessage = function(e) {
|
||||
callback(null, e.data);
|
||||
@ -287,21 +305,32 @@ app.crypto.Crypto = function(window, util) {
|
||||
worker.postMessage({
|
||||
type: 'encrypt',
|
||||
list: envelopes,
|
||||
pubkeyPem: keypair.pubkeyPem,
|
||||
privkeyPem: keypair.privkeyPem
|
||||
senderPrivkey: senderPrivkey,
|
||||
receiverPubkeys: receiverPubkeys
|
||||
});
|
||||
|
||||
} else {
|
||||
var batch = new cryptoLib.CryptoBatch(aes, rsa, util);
|
||||
var encryptedList = batch.encryptListForUser(envelopes);
|
||||
var batch = new cryptoLib.CryptoBatch(aes, rsa, util, _);
|
||||
var encryptedList = batch.encryptListForUser(envelopes, receiverPubkeys, senderPrivkey);
|
||||
callback(null, encryptedList);
|
||||
}
|
||||
};
|
||||
|
||||
this.decryptListForUser = function(list, recipientPubkey, callback) {
|
||||
if (window.Worker) {
|
||||
this.decryptListForUser = function(list, senderPubkeys, callback) {
|
||||
if (!senderPubkeys || senderPubkeys < 1) {
|
||||
callback({
|
||||
errMsg: 'Sender public keys must be set!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var keypair = rsa.exportKeys();
|
||||
var keypair = rsa.exportKeys();
|
||||
var receiverPrivkey = {
|
||||
_id: keypair._id,
|
||||
privateKey: keypair.privkeyPem
|
||||
};
|
||||
|
||||
if (window.Worker) {
|
||||
|
||||
var worker = new Worker(app.config.workerPath + '/crypto/crypto-batch-worker.js');
|
||||
worker.onmessage = function(e) {
|
||||
@ -310,13 +339,13 @@ app.crypto.Crypto = function(window, util) {
|
||||
worker.postMessage({
|
||||
type: 'decrypt',
|
||||
list: list,
|
||||
pubkeyPem: keypair.pubkeyPem,
|
||||
privkeyPem: keypair.privkeyPem
|
||||
receiverPrivkey: receiverPrivkey,
|
||||
senderPubkeys: senderPubkeys
|
||||
});
|
||||
|
||||
} else {
|
||||
var batch = new cryptoLib.CryptoBatch(aes, rsa, util);
|
||||
var decryptedList = batch.decryptListForUser(list);
|
||||
var batch = new cryptoLib.CryptoBatch(aes, rsa, util, _);
|
||||
var decryptedList = batch.decryptListForUser(list, senderPubkeys, receiverPrivkey);
|
||||
callback(null, decryptedList);
|
||||
}
|
||||
};
|
||||
|
@ -98,7 +98,9 @@ asyncTest("AES/RSA encrypt batch for User (Async/Worker)", 2, function() {
|
||||
collection = td.getEmailCollection(10);
|
||||
crypto_test.list = collection.toJSON();
|
||||
|
||||
crypto_test.crypto.encryptListForUser(crypto_test.list, null, function(err, encryptedList) {
|
||||
var receiverPubkeys = [crypto_test.crypto.getPublicKey()];
|
||||
|
||||
crypto_test.crypto.encryptListForUser(crypto_test.list, receiverPubkeys, function(err, encryptedList) {
|
||||
ok(!err && encryptedList, 'Encrypt list for user');
|
||||
equal(encryptedList.length, crypto_test.list.length, 'Length of list');
|
||||
crypto_test.encryptedList = encryptedList;
|
||||
@ -108,7 +110,10 @@ asyncTest("AES/RSA encrypt batch for User (Async/Worker)", 2, function() {
|
||||
});
|
||||
|
||||
asyncTest("AES/RSA decrypt batch for User (Async/Worker)", 3, function() {
|
||||
crypto_test.crypto.decryptListForUser(crypto_test.encryptedList, null, function(err, decryptedList) {
|
||||
|
||||
var senderPubkeys = [crypto_test.crypto.getPublicKey()];
|
||||
|
||||
crypto_test.crypto.decryptListForUser(crypto_test.encryptedList, senderPubkeys, function(err, decryptedList) {
|
||||
ok(!err && decryptedList, 'Decrypt list');
|
||||
equal(decryptedList.length, crypto_test.list.length, 'Length of list');
|
||||
deepEqual(decryptedList, crypto_test.list, 'Decrypted list is correct');
|
||||
|
Loading…
Reference in New Issue
Block a user