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) {
'use strict';
var symmetricUserKey = null, // the user's secret key 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
var keypair = null, // the user's keys used to encrypt item-keys
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
* encrypted secret key from storage and storing it in memory.
*/
this.init = function(emailAddress, password, keySize, ivSize, callback) {
this.emailAddress = emailAddress;
this.keySize = keySize;
this.ivSize = ivSize;
this.init = function(args, callback) {
var self = this;
this.emailAddress = args.emailAddress;
this.keySize = args.keySize;
this.ivSize = args.keySize;
// 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
var keyStore = new app.dao.LocalStorageDAO(window);
var storageId = emailAddress + '_encryptedSymmetricKey';
var storedKey = keyStore.read(storageId);
var storageId = args.emailAddress + '_encryptedKeypair';
var storedKeypair = keyStore.read(storageId);
// check if key exists
if (!storedKey) {
// generate key, encrypt and persist if none exists
symmetricUserKey = util.random(keySize);
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);
if (!storedKeypair) {
// generate keys, encrypt and persist if none exists
generateKeypair(keyStore, storageId, pbkdf2);
} else {
// decrypt key
try {
symmetricUserKey = aes.decrypt(storedKey.encryptedKey, pbkdf2, storedKey.keyIV);
} catch (ex) {
callback({
errMsg: 'Wrong password!'
});
decryptKeypair(storedKeypair, pbkdf2);
}
});
function generateKeypair(keyStore, storageId, pbkdf2) {
// generate RSA keypair in web worker
rsa.generateKeypair(rsa_test.keySize, function(err) {
if (err) {
callback(err);
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();
});
}
};
/**
@ -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
//

View File

@ -1,24 +1,24 @@
/**
* A Wrapper for Forge's RSA encryption
*/
app.crypto.RSA = function(forge) {
app.crypto.RSA = function(forge, util) {
'use strict';
var utl = forge.util;
var publicKey = null,
privateKey = null;
var keypair = null;
/**
* Initializes the RSA module by passing the user's keypair
* The private key is option and required only for decryption
* and signing
*/
this.init = function(pubkeyPem, privkeyPem) {
publicKey = forge.pki.publicKeyFromPem(pubkeyPem);
this.init = function(pubkeyPem, privkeyPem, keyId) {
keypair.publicKey = forge.pki.publicKeyFromPem(pubkeyPem);
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({
bits: keySize,
workerScript: app.config.workerPath + '/../../lib/forge/prime.worker.js'
}, function(err, keypair) {
if (err || !keypair.publicKey || !keypair.privateKey) {
}, function(err, newKeypair) {
if (err || !newKeypair || !newKeypair.publicKey || !newKeypair.privateKey) {
callback({
errMsg: 'RSA keygeneration failed!',
err: err
@ -37,8 +37,9 @@ app.crypto.RSA = function(forge) {
return;
}
publicKey = keypair.publicKey;
privateKey = keypair.privateKey;
keypair = newKeypair;
// generate unique keypair ID
keypair._id = util.UUID();
callback();
});
@ -49,8 +50,9 @@ app.crypto.RSA = function(forge) {
*/
this.exportKeys = function() {
return {
pubkeyPem: forge.pki.publicKeyToPem(publicKey),
privkeyPem: forge.pki.privateKeyToPem(privateKey)
_id: keypair._id,
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) {
// 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
return utl.encode64(ct);
};
@ -75,7 +77,7 @@ app.crypto.RSA = function(forge) {
// decode base64 ciphertext to utf8
var ctUtf8 = utl.decode64(ciphertext);
// 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
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));
});
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);
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');
start();

View File

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