mirror of
https://github.com/moparisthebest/mail
synced 2025-01-30 22:50:17 -05:00
refactored crypto for user to use RSA encrypt/sign
This commit is contained in:
parent
413a99a04f
commit
fcf64569b2
@ -66,15 +66,19 @@ app.crypto.Crypto = function(window, util) {
|
||||
}
|
||||
|
||||
function decryptKeypair(storedKeypair, pbkdf2) {
|
||||
var keypairJson, keypair;
|
||||
// try to decrypt with pbkdf2
|
||||
try {
|
||||
var keypairJson = aes.decrypt(storedKeypair.encryptedKeys, pbkdf2, storedKeypair.keyIV);
|
||||
var keypair = JSON.parse(keypairJson);
|
||||
keypairJson = aes.decrypt(storedKeypair.encryptedKeys, pbkdf2, storedKeypair.keyIV);
|
||||
keypair = JSON.parse(keypairJson);
|
||||
} catch (ex) {
|
||||
callback({
|
||||
errMsg: 'Wrong password!'
|
||||
});
|
||||
return;
|
||||
}
|
||||
// set rsa keys
|
||||
rsa.init(keypair.pubkeyPem, keypair.privkeyPem, keypair._id);
|
||||
|
||||
callback();
|
||||
}
|
||||
@ -205,22 +209,7 @@ app.crypto.Crypto = function(window, util) {
|
||||
// En/Decrypt something speficially using the user's secret key
|
||||
//
|
||||
|
||||
this.aesEncryptForUser = function(plaintext, iv, callback) {
|
||||
var ciphertext = aes.encrypt(plaintext, symmetricUserKey, iv);
|
||||
callback(ciphertext);
|
||||
};
|
||||
this.aesDecryptForUser = function(ciphertext, iv, callback) {
|
||||
var decrypted = aes.decrypt(ciphertext, symmetricUserKey, iv);
|
||||
callback(decrypted);
|
||||
};
|
||||
this.aesEncryptForUserSync = function(plaintext, iv) {
|
||||
return aes.encrypt(plaintext, symmetricUserKey, iv);
|
||||
};
|
||||
this.aesDecryptForUserSync = function(ciphertext, iv) {
|
||||
return aes.decrypt(ciphertext, symmetricUserKey, iv);
|
||||
};
|
||||
|
||||
this.aesEncryptListForUser = function(list, callback) {
|
||||
this.encryptListForUser = function(list, recipientPubkey, callback) {
|
||||
var envelope, envelopes = [],
|
||||
self = this;
|
||||
|
||||
@ -242,26 +231,33 @@ app.crypto.Crypto = function(window, util) {
|
||||
encryptedList.forEach(function(i) {
|
||||
// process new values
|
||||
i.itemIV = i.iv;
|
||||
i.keyIV = util.random(self.ivSize);
|
||||
i.encryptedKey = self.aesEncryptForUserSync(i.key, i.keyIV);
|
||||
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;
|
||||
});
|
||||
|
||||
callback(encryptedList);
|
||||
callback(null, encryptedList);
|
||||
});
|
||||
};
|
||||
|
||||
this.aesDecryptListForUser = function(encryptedList, callback) {
|
||||
this.decryptListForUser = function(encryptedList, recipientPubkey, callback) {
|
||||
var list = [],
|
||||
self = this;
|
||||
|
||||
// decrypt keys for user
|
||||
encryptedList.forEach(function(i) {
|
||||
// decrypt item key
|
||||
i.key = self.aesDecryptForUserSync(i.encryptedKey, i.keyIV);
|
||||
// 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;
|
||||
@ -275,7 +271,7 @@ app.crypto.Crypto = function(window, util) {
|
||||
list.push(i.plaintext);
|
||||
});
|
||||
|
||||
callback(list);
|
||||
callback(null, list);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -14,11 +14,13 @@ app.crypto.RSA = function(forge, util) {
|
||||
* and signing
|
||||
*/
|
||||
this.init = function(pubkeyPem, privkeyPem, keyId) {
|
||||
keypair.publicKey = forge.pki.publicKeyFromPem(pubkeyPem);
|
||||
keypair = {
|
||||
_id: keyId,
|
||||
publicKey: forge.pki.publicKeyFromPem(pubkeyPem)
|
||||
};
|
||||
if (privkeyPem) {
|
||||
keypair.privateKey = forge.pki.privateKeyFromPem(privkeyPem);
|
||||
}
|
||||
keypair._id = keyId;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -44,15 +44,13 @@ var Util = function(window, uuid, crypt) {
|
||||
* @list list [Array] The list of items to encrypt
|
||||
*/
|
||||
this.encryptList = function(aes, list) {
|
||||
var json, ct, outList = [];
|
||||
var outList = [];
|
||||
|
||||
list.forEach(function(i) {
|
||||
// stringify to JSON before encryption
|
||||
json = JSON.stringify(i.plaintext);
|
||||
ct = aes.encrypt(json, i.key, i.iv);
|
||||
outList.push({
|
||||
id: i.id,
|
||||
ciphertext: ct,
|
||||
ciphertext: aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv),
|
||||
key: i.key,
|
||||
iv: i.iv
|
||||
});
|
||||
@ -67,15 +65,13 @@ var Util = function(window, uuid, crypt) {
|
||||
* @list list [Array] The list of items to decrypt
|
||||
*/
|
||||
this.decryptList = function(aes, list) {
|
||||
var json, pt, outList = [];
|
||||
var outList = [];
|
||||
|
||||
list.forEach(function(i) {
|
||||
// decrypt JSON and parse to object literal
|
||||
json = aes.decrypt(i.ciphertext, i.key, i.iv);
|
||||
pt = JSON.parse(json);
|
||||
outList.push({
|
||||
id: i.id,
|
||||
plaintext: pt,
|
||||
plaintext: JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv)),
|
||||
key: i.key,
|
||||
iv: i.iv
|
||||
});
|
||||
|
@ -32,33 +32,7 @@ asyncTest("PBKDF2 (Async/Worker)", 1, function() {
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("En/Decrypt for User", 4, function() {
|
||||
var secret = "Secret stuff";
|
||||
|
||||
var itemKey = crypto_test.util.random(crypto_test.keySize);
|
||||
var itemIV = crypto_test.util.random(crypto_test.ivSize);
|
||||
var keyIV = crypto_test.util.random(crypto_test.ivSize);
|
||||
|
||||
crypto_test.crypto.aesEncrypt(secret, itemKey, itemIV, function(ciphertext) {
|
||||
ok(ciphertext, 'Encrypt item');
|
||||
|
||||
crypto_test.crypto.aesEncryptForUser(itemKey, keyIV, function(encryptedKey) {
|
||||
ok(encryptedKey, 'Encrypt item key');
|
||||
|
||||
crypto_test.crypto.aesDecryptForUser(encryptedKey, keyIV, function(decryptedKey) {
|
||||
equal(decryptedKey, itemKey, 'Decrypt item key');
|
||||
|
||||
crypto_test.crypto.aesDecrypt(ciphertext, decryptedKey, itemIV, function(decrypted) {
|
||||
equal(decrypted, secret, 'Decrypt item');
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("AES (Async/Worker)", 2, function() {
|
||||
asyncTest("AES en/decrypt (Async/Worker)", 2, function() {
|
||||
var secret = 'Big secret';
|
||||
|
||||
var key = crypto_test.util.random(crypto_test.keySize);
|
||||
@ -75,7 +49,7 @@ asyncTest("AES (Async/Worker)", 2, function() {
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("AES batch (Async/Worker)", 5, function() {
|
||||
asyncTest("AES en/decrypt batch (Async/Worker)", 5, function() {
|
||||
// generate test data
|
||||
var collection, list, td = new TestData();
|
||||
|
||||
@ -96,23 +70,28 @@ asyncTest("AES batch (Async/Worker)", 5, function() {
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("AES batch for User (Async/Worker)", 5, function() {
|
||||
asyncTest("AES/RSA encrypt batch for User (Async/Worker)", 2, function() {
|
||||
// generate test data
|
||||
var collection, list, td = new TestData();
|
||||
var collection, td = new TestData();
|
||||
|
||||
collection = td.getEmailCollection(100);
|
||||
list = collection.toJSON();
|
||||
collection = td.getEmailCollection(10);
|
||||
crypto_test.list = collection.toJSON();
|
||||
|
||||
crypto_test.crypto.aesEncryptListForUser(list, function(encryptedList) {
|
||||
ok(encryptedList, 'Encrypt list for user');
|
||||
equal(encryptedList.length, list.length, 'Length of list');
|
||||
crypto_test.crypto.encryptListForUser(crypto_test.list, null, function(err, encryptedList) {
|
||||
ok(!err && encryptedList, 'Encrypt list for user');
|
||||
equal(encryptedList.length, crypto_test.list.length, 'Length of list');
|
||||
crypto_test.encryptedList = encryptedList;
|
||||
|
||||
crypto_test.crypto.aesDecryptListForUser(encryptedList, function(decryptedList) {
|
||||
ok(decryptedList, 'Decrypt list');
|
||||
equal(decryptedList.length, list.length, 'Length of list');
|
||||
deepEqual(decryptedList, list, 'Decrypted list is correct');
|
||||
|
||||
start();
|
||||
});
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest("AES/RSA decrypt batch for User (Async/Worker)", 3, function() {
|
||||
crypto_test.crypto.decryptListForUser(crypto_test.encryptedList, null, 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');
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user