From 596951a1f0a43d44c29a6155a24b7f969dcee188 Mon Sep 17 00:00:00 2001 From: Lloyd Hilaiel <lloyd@hilaiel.com> Date: Tue, 23 Aug 2011 18:28:33 +0300 Subject: [PATCH] upgrade to bcrypt 0.2.4 and move to bcrypt async apis, this keeps us from blocking the web server thread and leverages the threading support in the bcrypt library for better compute throughput and responsiveness. --- browserid/lib/wsapi.js | 90 ++++++++++++++++++++++++++---------------- package.json | 2 +- performance/run.js | 2 +- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/browserid/lib/wsapi.js b/browserid/lib/wsapi.js index 9f8840e5b..831736a17 100644 --- a/browserid/lib/wsapi.js +++ b/browserid/lib/wsapi.js @@ -139,35 +139,49 @@ function setup(app) { } // bcrypt the password - stageParams['hash'] = bcrypt.encrypt_sync(stageParams.pass, bcrypt.gen_salt_sync(10)); - - try { - // upon success, stage_user returns a secret (that'll get baked into a url - // and given to the user), on failure it throws - db.stageUser(stageParams, function(secret) { - // store the email being registered in the session data - if (!req.session) req.session = {}; - - // store inside the session the details of this pending verification - req.session.pendingVerification = { - email: stageParams.email, - hash: stageParams.hash // we must store both email and password to handle the case where - // a user re-creates an account - specifically, registration status - // must ensure the new credentials work to properly verify that - // the user has clicked throught the email link. note, this salted, bcrypted - // representation of a user's password will get thrust into an encrypted cookie - // served over an encrypted (SSL) session. guten, yah. - }; + bcrypt.gen_salt(10, function (err, salt) { + if (err) { + winston.error("error generating salt with bcrypt: " + err); + return resp.json(false); + } - resp.json(true); + bcrypt.encrypt(stageParams.pass, salt, function(err, hash) { + if (err) { + winston.error("error generating password hash with bcrypt: " + err); + return resp.json(false); + } - // let's now kick out a verification email! - email.sendVerificationEmail(stageParams.email, stageParams.site, secret); + stageParams['hash'] = hash; + + try { + // upon success, stage_user returns a secret (that'll get baked into a url + // and given to the user), on failure it throws + db.stageUser(stageParams, function(secret) { + // store the email being registered in the session data + if (!req.session) req.session = {}; + + // store inside the session the details of this pending verification + req.session.pendingVerification = { + email: stageParams.email, + hash: stageParams.hash // we must store both email and password to handle the case where + // a user re-creates an account - specifically, registration status + // must ensure the new credentials work to properly verify that + // the user has clicked throught the email link. note, this salted, bcrypted + // representation of a user's password will get thrust into an encrypted cookie + // served over an encrypted (SSL) session. guten, yah. + }; + + resp.json(true); + + // let's now kick out a verification email! + email.sendVerificationEmail(stageParams.email, stageParams.site, secret); + }); + } catch(e) { + // we should differentiate tween' 400 and 500 here. + httputils.badRequest(resp, e.toString()); + } }); - } catch(e) { - // we should differentiate tween' 400 and 500 here. - httputils.badRequest(resp, e.toString()); - } + }); }); app.get('/wsapi/registration_status', function(req, resp) { @@ -217,17 +231,23 @@ function setup(app) { app.post('/wsapi/authenticate_user', checkParams(["email", "pass"]), function(req, resp) { db.checkAuth(req.body.email, function(hash) { - var success = - (typeof hash === 'string' && - typeof req.body.pass === 'string' && - bcrypt.compare_sync(req.body.pass, hash)); - - if (success) { - if (!req.session) req.session = {}; - req.session.authenticatedUser = req.body.email; + if (typeof hash !== 'string' || + typeof req.body.pass !== 'string') + { + return resp.json(false); } - resp.json(success); + bcrypt.compare(req.body.pass, hash, function (err, success) { + if (err) { + winston.warn("error comparing passwords with bcrypt: " + err); + success = false; + } + if (success) { + if (!req.session) req.session = {}; + req.session.authenticatedUser = req.body.email; + } + resp.json(success); + }); }); }); diff --git a/package.json b/package.json index 0e8e91a19..da47ac2b0 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ , "nodemailer": "0.1.18" , "mustache": "0.3.1-dev" , "vows": "0.5.8" - , "bcrypt": "0.2.3" + , "bcrypt": "0.2.4" , "ejs": "0.4.3" , "temp": "0.2.0" , "express-csrf": "0.3.2" diff --git a/performance/run.js b/performance/run.js index c75522a8b..fea7840d0 100755 --- a/performance/run.js +++ b/performance/run.js @@ -280,7 +280,7 @@ function poll() { } // always start out by creating a bunch of users -var NUM_INITIAL_USERS = 50; +var NUM_INITIAL_USERS = 100; // if an explicit target was specified, let's output what that means // in understandable terms -- GitLab