1
0
mirror of https://github.com/moparisthebest/mail synced 2024-11-25 10:22:18 -05:00

started refacroting crypto

This commit is contained in:
Tankred Hase 2013-05-14 20:28:12 +02:00
parent 1b95066e12
commit c9c53598e8
4 changed files with 78 additions and 60 deletions

View File

@ -5,56 +5,80 @@
app.crypto.Crypto = function(window, util) { app.crypto.Crypto = function(window, util) {
'use strict'; 'use strict';
var symmetricUserKey = null, // the user's secret key used to encrypt item-keys var keypair = null, // the user's keys used to encrypt item-keys
keyId = null, // the key ID linking the user's key set aes = new app.crypto.AesCBC(forge), // use AES-CBC mode by default
aes = new app.crypto.AesCBC(forge); // use AES-CBC mode by default rsa = new app.crypto.RSA(forge, util); // use RSA for asym. crypto
/** /**
* Initializes the crypto modules by fetching the user's * Initializes the crypto modules by fetching the user's
* encrypted secret key from storage and storing it in memory. * encrypted secret key from storage and storing it in memory.
*/ */
this.init = function(emailAddress, password, keySize, ivSize, callback) { this.init = function(args, callback) {
this.emailAddress = emailAddress; var self = this;
this.keySize = keySize;
this.ivSize = ivSize; this.emailAddress = args.emailAddress;
this.keySize = args.keySize;
this.ivSize = args.keySize;
// derive PBKDF2 from password in web worker thread // derive PBKDF2 from password in web worker thread
this.deriveKey(password, keySize, function(pbkdf2) { this.deriveKey(args.password, args.keySize, function(pbkdf2) {
// fetch user's encrypted secret key from keychain/storage // fetch user's encrypted secret key from keychain/storage
var keyStore = new app.dao.LocalStorageDAO(window); var keyStore = new app.dao.LocalStorageDAO(window);
var storageId = emailAddress + '_encryptedSymmetricKey'; var storageId = args.emailAddress + '_encryptedKeypair';
var storedKey = keyStore.read(storageId); var storedKeypair = keyStore.read(storageId);
// check if key exists // check if key exists
if (!storedKey) { if (!storedKeypair) {
// generate key, encrypt and persist if none exists // generate keys, encrypt and persist if none exists
symmetricUserKey = util.random(keySize); generateKeypair(keyStore, storageId, pbkdf2);
var iv = util.random(ivSize);
var key = aes.encrypt(symmetricUserKey, pbkdf2, iv);
storedKey = {
_id: util.UUID(),
userId: emailAddress,
encryptedKey: key,
keyIV: iv
};
keyStore.persist(storageId, storedKey);
} else { } else {
// decrypt key // decrypt key
try { decryptKeypair(storedKeypair, pbkdf2);
symmetricUserKey = aes.decrypt(storedKey.encryptedKey, pbkdf2, storedKey.keyIV); }
} catch (ex) {
callback({ });
errMsg: 'Wrong password!'
}); function generateKeypair(keyStore, storageId, pbkdf2) {
// generate RSA keypair in web worker
rsa.generateKeypair(rsa_test.keySize, function(err) {
if (err) {
callback(err);
return; return;
} }
keypair = rsa.exportKeys();
// encrypt keypair
var iv = util.random(self.ivSize);
var encryptedKeys = aes.encrypt(JSON.stringify(keypair), pbkdf2, iv);
// store encrypted keypair
var newStoredKeypair = {
_id: keypair._id,
userId: args.emailAddress,
encryptedKeys: encryptedKeys,
keyIV: iv
};
keyStore.persist(storageId, newStoredKeypair);
callback();
});
}
function decryptKeypair(storedKeypair, pbkdf2) {
try {
var keypairJson = aes.decrypt(storedKeypair.encryptedKeys, pbkdf2, storedKeypair.keyIV);
keypair = JSON.parse(keypairJson);
} catch (ex) {
callback({
errMsg: 'Wrong password!'
});
return;
} }
keyId = storedKey._id;
callback(); callback();
}); }
}; };
/** /**
@ -86,18 +110,6 @@ app.crypto.Crypto = function(window, util) {
} }
}; };
/**
* Derive an asymmetric keypait from the user's secret
*/
this.deriveKeyPair = function(naclCrypto, callback) {
naclCrypto.generateKeypair(symmetricUserKey, function(keys) {
if (keyId) {
keys.id = keyId;
}
callback(keys);
});
};
// //
// En/Decrypts single item // En/Decrypts single item
// //

View File

@ -1,24 +1,24 @@
/** /**
* A Wrapper for Forge's RSA encryption * A Wrapper for Forge's RSA encryption
*/ */
app.crypto.RSA = function(forge) { app.crypto.RSA = function(forge, util) {
'use strict'; 'use strict';
var utl = forge.util; var utl = forge.util;
var publicKey = null, var keypair = null;
privateKey = null;
/** /**
* Initializes the RSA module by passing the user's keypair * Initializes the RSA module by passing the user's keypair
* The private key is option and required only for decryption * The private key is option and required only for decryption
* and signing * and signing
*/ */
this.init = function(pubkeyPem, privkeyPem) { this.init = function(pubkeyPem, privkeyPem, keyId) {
publicKey = forge.pki.publicKeyFromPem(pubkeyPem); keypair.publicKey = forge.pki.publicKeyFromPem(pubkeyPem);
if (privkeyPem) { if (privkeyPem) {
privateKey = forge.pki.privateKeyFromPem(privkeyPem); keypair.privateKey = forge.pki.privateKeyFromPem(privkeyPem);
} }
keypair._id = keyId;
}; };
/** /**
@ -28,8 +28,8 @@ app.crypto.RSA = function(forge) {
forge.rsa.generateKeyPair({ forge.rsa.generateKeyPair({
bits: keySize, bits: keySize,
workerScript: app.config.workerPath + '/../../lib/forge/prime.worker.js' workerScript: app.config.workerPath + '/../../lib/forge/prime.worker.js'
}, function(err, keypair) { }, function(err, newKeypair) {
if (err || !keypair.publicKey || !keypair.privateKey) { if (err || !newKeypair || !newKeypair.publicKey || !newKeypair.privateKey) {
callback({ callback({
errMsg: 'RSA keygeneration failed!', errMsg: 'RSA keygeneration failed!',
err: err err: err
@ -37,8 +37,9 @@ app.crypto.RSA = function(forge) {
return; return;
} }
publicKey = keypair.publicKey; keypair = newKeypair;
privateKey = keypair.privateKey; // generate unique keypair ID
keypair._id = util.UUID();
callback(); callback();
}); });
@ -49,8 +50,9 @@ app.crypto.RSA = function(forge) {
*/ */
this.exportKeys = function() { this.exportKeys = function() {
return { return {
pubkeyPem: forge.pki.publicKeyToPem(publicKey), _id: keypair._id,
privkeyPem: forge.pki.privateKeyToPem(privateKey) pubkeyPem: forge.pki.publicKeyToPem(keypair.publicKey),
privkeyPem: forge.pki.privateKeyToPem(keypair.privateKey)
}; };
}; };
@ -61,7 +63,7 @@ app.crypto.RSA = function(forge) {
*/ */
this.encrypt = function(plaintext) { this.encrypt = function(plaintext) {
// encode plaintext to utf8 and encrypt // encode plaintext to utf8 and encrypt
var ct = publicKey.encrypt(utl.encodeUtf8(plaintext)); var ct = keypair.publicKey.encrypt(utl.encodeUtf8(plaintext));
// encode ciphtext to base64 // encode ciphtext to base64
return utl.encode64(ct); return utl.encode64(ct);
}; };
@ -75,7 +77,7 @@ app.crypto.RSA = function(forge) {
// decode base64 ciphertext to utf8 // decode base64 ciphertext to utf8
var ctUtf8 = utl.decode64(ciphertext); var ctUtf8 = utl.decode64(ciphertext);
// decrypt and decode to utf16 // decrypt and decode to utf16
return utl.decodeUtf8(privateKey.decrypt(ctUtf8)); return utl.decodeUtf8(keypair.privateKey.decrypt(ctUtf8));
}; };
/** /**
@ -91,7 +93,7 @@ app.crypto.RSA = function(forge) {
}); });
// encode signature to base64 // encode signature to base64
return utl.encode64(privateKey.sign(sha)); return utl.encode64(keypair.privateKey.sign(sha));
}; };
/** /**
@ -110,7 +112,7 @@ app.crypto.RSA = function(forge) {
sha.update(utl.decode64(i)); sha.update(utl.decode64(i));
}); });
return publicKey.verify(sha.digest().getBytes(), sigUtf8); return keypair.publicKey.verify(sha.digest().getBytes(), sigUtf8);
}; };
}; };

View File

@ -13,7 +13,11 @@ asyncTest("Init", 2, function() {
crypto_test.crypto = new app.crypto.Crypto(window, crypto_test.util); crypto_test.crypto = new app.crypto.Crypto(window, crypto_test.util);
ok(crypto_test.crypto, 'Crypto'); ok(crypto_test.crypto, 'Crypto');
crypto_test.crypto.init(crypto_test.user, crypto_test.password, crypto_test.keySize, crypto_test.ivSize, function() { crypto_test.crypto.init({
emailAddress: crypto_test.user,
password: crypto_test.password,
keySize: crypto_test.keySize
}, function() {
ok(true, 'Init crypto'); ok(true, 'Init crypto');
start(); start();

View File

@ -2,7 +2,7 @@ module("RSA Crypto");
var rsa_test = { var rsa_test = {
keySize: 1024, keySize: 1024,
rsa: new app.crypto.RSA(forge), rsa: new app.crypto.RSA(forge, new app.crypto.Util(window, uuid)),
test_message: '06a9214036b8a15b512e03d534120006' test_message: '06a9214036b8a15b512e03d534120006'
}; };