mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 00:42:20 -05:00
started refacroting crypto
This commit is contained in:
parent
1b95066e12
commit
c9c53598e8
@ -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
|
||||
//
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
};
|
@ -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();
|
||||
|
@ -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'
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user