refactored crypto for user to use RSA encrypt/sign

This commit is contained in:
Tankred Hase 2013-05-15 12:26:32 +02:00
parent 413a99a04f
commit fcf64569b2
4 changed files with 49 additions and 76 deletions

View File

@ -66,15 +66,19 @@ app.crypto.Crypto = function(window, util) {
} }
function decryptKeypair(storedKeypair, pbkdf2) { function decryptKeypair(storedKeypair, pbkdf2) {
var keypairJson, keypair;
// try to decrypt with pbkdf2
try { try {
var keypairJson = aes.decrypt(storedKeypair.encryptedKeys, pbkdf2, storedKeypair.keyIV); keypairJson = aes.decrypt(storedKeypair.encryptedKeys, pbkdf2, storedKeypair.keyIV);
var keypair = JSON.parse(keypairJson); keypair = JSON.parse(keypairJson);
} catch (ex) { } catch (ex) {
callback({ callback({
errMsg: 'Wrong password!' errMsg: 'Wrong password!'
}); });
return; return;
} }
// set rsa keys
rsa.init(keypair.pubkeyPem, keypair.privkeyPem, keypair._id);
callback(); callback();
} }
@ -205,22 +209,7 @@ app.crypto.Crypto = function(window, util) {
// En/Decrypt something speficially using the user's secret key // En/Decrypt something speficially using the user's secret key
// //
this.aesEncryptForUser = function(plaintext, iv, callback) { this.encryptListForUser = function(list, recipientPubkey, 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) {
var envelope, envelopes = [], var envelope, envelopes = [],
self = this; self = this;
@ -242,26 +231,33 @@ app.crypto.Crypto = function(window, util) {
encryptedList.forEach(function(i) { encryptedList.forEach(function(i) {
// process new values // process new values
i.itemIV = i.iv; i.itemIV = i.iv;
i.keyIV = util.random(self.ivSize); i.encryptedKey = rsa.encrypt(i.key);
i.encryptedKey = self.aesEncryptForUserSync(i.key, i.keyIV); i.keyIV = rsa.sign([i.itemIV, i.encryptedKey, i.ciphertext]);
// delete old ones // delete old ones
delete i.iv; delete i.iv;
delete i.key; delete i.key;
}); });
callback(encryptedList); callback(null, encryptedList);
}); });
}; };
this.aesDecryptListForUser = function(encryptedList, callback) { this.decryptListForUser = function(encryptedList, recipientPubkey, callback) {
var list = [], var list = [],
self = this; self = this;
// decrypt keys for user // decrypt keys for user
encryptedList.forEach(function(i) { encryptedList.forEach(function(i) {
// decrypt item key // verify signature
i.key = self.aesDecryptForUserSync(i.encryptedKey, i.keyIV); 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.iv = i.itemIV;
i.key = rsa.decrypt(i.encryptedKey);
// delete old values // delete old values
delete i.keyIV; delete i.keyIV;
delete i.itemIV; delete i.itemIV;
@ -275,7 +271,7 @@ app.crypto.Crypto = function(window, util) {
list.push(i.plaintext); list.push(i.plaintext);
}); });
callback(list); callback(null, list);
}); });
}; };

View File

@ -14,11 +14,13 @@ app.crypto.RSA = function(forge, util) {
* and signing * and signing
*/ */
this.init = function(pubkeyPem, privkeyPem, keyId) { this.init = function(pubkeyPem, privkeyPem, keyId) {
keypair.publicKey = forge.pki.publicKeyFromPem(pubkeyPem); keypair = {
_id: keyId,
publicKey: forge.pki.publicKeyFromPem(pubkeyPem)
};
if (privkeyPem) { if (privkeyPem) {
keypair.privateKey = forge.pki.privateKeyFromPem(privkeyPem); keypair.privateKey = forge.pki.privateKeyFromPem(privkeyPem);
} }
keypair._id = keyId;
}; };
/** /**

View File

@ -44,15 +44,13 @@ var Util = function(window, uuid, crypt) {
* @list list [Array] The list of items to encrypt * @list list [Array] The list of items to encrypt
*/ */
this.encryptList = function(aes, list) { this.encryptList = function(aes, list) {
var json, ct, outList = []; var outList = [];
list.forEach(function(i) { list.forEach(function(i) {
// stringify to JSON before encryption // stringify to JSON before encryption
json = JSON.stringify(i.plaintext);
ct = aes.encrypt(json, i.key, i.iv);
outList.push({ outList.push({
id: i.id, id: i.id,
ciphertext: ct, ciphertext: aes.encrypt(JSON.stringify(i.plaintext), i.key, i.iv),
key: i.key, key: i.key,
iv: i.iv iv: i.iv
}); });
@ -67,15 +65,13 @@ var Util = function(window, uuid, crypt) {
* @list list [Array] The list of items to decrypt * @list list [Array] The list of items to decrypt
*/ */
this.decryptList = function(aes, list) { this.decryptList = function(aes, list) {
var json, pt, outList = []; var outList = [];
list.forEach(function(i) { list.forEach(function(i) {
// decrypt JSON and parse to object literal // decrypt JSON and parse to object literal
json = aes.decrypt(i.ciphertext, i.key, i.iv);
pt = JSON.parse(json);
outList.push({ outList.push({
id: i.id, id: i.id,
plaintext: pt, plaintext: JSON.parse(aes.decrypt(i.ciphertext, i.key, i.iv)),
key: i.key, key: i.key,
iv: i.iv iv: i.iv
}); });

View File

@ -32,33 +32,7 @@ asyncTest("PBKDF2 (Async/Worker)", 1, function() {
}); });
}); });
asyncTest("En/Decrypt for User", 4, function() { asyncTest("AES en/decrypt (Async/Worker)", 2, 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() {
var secret = 'Big secret'; var secret = 'Big secret';
var key = crypto_test.util.random(crypto_test.keySize); 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 // generate test data
var collection, list, td = new TestData(); 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 // generate test data
var collection, list, td = new TestData(); var collection, td = new TestData();
collection = td.getEmailCollection(100); collection = td.getEmailCollection(10);
list = collection.toJSON(); crypto_test.list = collection.toJSON();
crypto_test.crypto.aesEncryptListForUser(list, function(encryptedList) { crypto_test.crypto.encryptListForUser(crypto_test.list, null, function(err, encryptedList) {
ok(encryptedList, 'Encrypt list for user'); ok(!err && encryptedList, 'Encrypt list for user');
equal(encryptedList.length, list.length, 'Length of list'); 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();
}); });
}); });