diff --git a/src/js/crypto/crypto.js b/src/js/crypto/crypto.js index d087e62..0fad4d1 100644 --- a/src/js/crypto/crypto.js +++ b/src/js/crypto/crypto.js @@ -81,12 +81,13 @@ app.crypto.Crypto = function(window, util) { /** * Derive an asymmetric keypait from the user's secret */ - this.deriveKeyPair = function(naclCrypto) { - var keys = naclCrypto.generateKeypair(symmetricUserKey); - if (keyId) { - keys.id = keyId; - } - return keys; + this.deriveKeyPair = function(naclCrypto, callback) { + naclCrypto.generateKeypair(symmetricUserKey, function(keys) { + if (keyId) { + keys.id = keyId; + } + callback(keys); + }); }; // diff --git a/src/js/crypto/nacl-crypto.js b/src/js/crypto/nacl-crypto.js index 8b0f6f1..d2eb5cc 100644 --- a/src/js/crypto/nacl-crypto.js +++ b/src/js/crypto/nacl-crypto.js @@ -8,21 +8,49 @@ var NaclCrypto = function(nacl, util) { * Generates a baes64 encoded keypair for use with NaCl * @param seed [String] A base64 encoded (pseudo) random seed e.g. PBKDF2 */ - this.generateKeypair = function(seed) { - var keys; + this.generateKeypair = function(seed, callback) { + var keys, seedBuf; if (seed) { - var seedBuf = nacl.encode_latin1(util.base642Str(seed)); - keys = nacl.crypto_box_keypair_from_seed(seedBuf); - } else { - keys = nacl.crypto_box_keypair(); - } + // do key deterministic derivation from pseudo random seed + seedBuf = nacl.encode_latin1(util.base642Str(seed)); - return { - id: util.UUID(), - boxPk: util.str2Base64(nacl.decode_latin1(keys.boxPk)), - boxSk: util.str2Base64(nacl.decode_latin1(keys.boxSk)) - }; + if (Worker) { + + var worker = new Worker(app.config.workerPath + '/crypto/nacl-worker.js'); + worker.onmessage = function(e) { + callback({ + id: util.UUID(), + boxPk: util.str2Base64(nacl.decode_latin1(e.data.boxPk)), + boxSk: util.str2Base64(nacl.decode_latin1(e.data.boxSk)) + }); + }; + worker.postMessage({ + type: 'keygen', + seed: seedBuf + }); + + } else { + // no web worker support + keys = nacl.crypto_box_keypair_from_seed(seedBuf); + + callback({ + id: util.UUID(), + boxPk: util.str2Base64(nacl.decode_latin1(keys.boxPk)), + boxSk: util.str2Base64(nacl.decode_latin1(keys.boxSk)) + }); + } + + } else { + // generate keypiar from random values + keys = nacl.crypto_box_keypair(); + + callback({ + id: util.UUID(), + boxPk: util.str2Base64(nacl.decode_latin1(keys.boxPk)), + boxSk: util.str2Base64(nacl.decode_latin1(keys.boxSk)) + }); + } }; /** diff --git a/src/js/crypto/nacl-worker.js b/src/js/crypto/nacl-worker.js index 4a99613..7fada0d 100644 --- a/src/js/crypto/nacl-worker.js +++ b/src/js/crypto/nacl-worker.js @@ -13,7 +13,15 @@ var args = e.data, output = null; - if (args.type === 'encrypt' && args.plaintext && args.nonce && args.recipientPk && args.senderSk) { + if (args.type === 'keygen') { + // generate keypair + if (args.seed) { + output = nacl.crypto_box_keypair_from_seed(args.seed); + } else { + output = nacl.crypto_box_keypair(); + } + + } else if (args.type === 'encrypt' && args.plaintext && args.nonce && args.recipientPk && args.senderSk) { // start encryption output = nacl.crypto_box(args.plaintext, args.nonce, args.recipientPk, args.senderSk); diff --git a/src/js/dao/email-dao.js b/src/js/dao/email-dao.js index a211664..a09f738 100644 --- a/src/js/dao/email-dao.js +++ b/src/js/dao/email-dao.js @@ -36,15 +36,18 @@ app.dao.EmailDAO = function(_, crypto, devicestorage, cloudstorage, naclCrypto, function initNaclCrypto() { // derive keypair from user's secret key - keypair = crypto.deriveKeyPair(naclCrypto); - //publish public key to cloud service - var pubkey = new app.model.PublicKey({ - _id: keypair.id, - userId: account.get('emailAddress'), - publicKey: keypair.boxPk - }); - cloudstorage.putPublicKey(pubkey.toJSON(), function(err) { - callback(err); + crypto.deriveKeyPair(naclCrypto, function(generated) { + keypair = generated; + + //publish public key to cloud service + var pubkey = new app.model.PublicKey({ + _id: keypair.id, + userId: account.get('emailAddress'), + publicKey: keypair.boxPk + }); + cloudstorage.putPublicKey(pubkey.toJSON(), function(err) { + callback(err); + }); }); } }; diff --git a/test/unit/nacl-crypto-test.js b/test/unit/nacl-crypto-test.js index d2d7aa5..215ea5e 100644 --- a/test/unit/nacl-crypto-test.js +++ b/test/unit/nacl-crypto-test.js @@ -14,22 +14,30 @@ test("Init", 1, function() { nacl_test.crypto = new app.crypto.NaclCrypto(nacl, nacl_test.util); }); -test("Generate Keypair from seed", 1, function() { +asyncTest("Generate Keypair from seed", 1, function() { // generate keypair from seed var seed = nacl_test.util.random(128); - var keys = nacl_test.crypto.generateKeypair(seed); - ok(keys.boxSk && keys.boxPk && keys.id, "Keypair: " + JSON.stringify(keys)); + nacl_test.crypto.generateKeypair(seed, function(keys) { + ok(keys.boxSk && keys.boxPk && keys.id, "Keypair: " + JSON.stringify(keys)); + + start(); + }); }); -test("Generate Keypair", 2, function() { +asyncTest("Generate Keypair", 2, function() { // generate keypair - var senderKeypair = nacl_test.crypto.generateKeypair(); - ok(senderKeypair.boxSk && senderKeypair.boxPk, "Sender keypair: " + JSON.stringify(senderKeypair)); - var recipientKeypair = nacl_test.crypto.generateKeypair(); - ok(recipientKeypair.boxSk && recipientKeypair.boxPk, "Receiver keypair: " + JSON.stringify(recipientKeypair)); + nacl_test.crypto.generateKeypair(null, function(senderKeypair) { + ok(senderKeypair.boxSk && senderKeypair.boxPk, "Sender keypair: " + JSON.stringify(senderKeypair)); - nacl_test.senderKeypair = senderKeypair; - nacl_test.recipientKeypair = recipientKeypair; + nacl_test.crypto.generateKeypair(null, function(recipientKeypair) { + ok(recipientKeypair.boxSk && recipientKeypair.boxPk, "Receiver keypair: " + JSON.stringify(recipientKeypair)); + + nacl_test.senderKeypair = senderKeypair; + nacl_test.recipientKeypair = recipientKeypair; + + start(); + }); + }); }); test("Asymmetric En/Decrypt (Synchronous)", 3, function() {