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) {
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);
});
};

View File

@ -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;
};
/**

View File

@ -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
});

View File

@ -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();
});
});