Make Meteor.user passwords more secure using 'bcrypt-salt' (Meteor 1.6.1 or greater)


With the recent addition of Accounts._options.bcryptRounds in Meteor v1.6.1 it is now possible to set the number of saltRounds bcrypt uses to calculate hashes.

I recently tried to use a custom value to increase the security of Meteor user passwords.

The default value is 10 rounds. When first looking into this, I wasn’t exactly sure what a ‘good’ number would be. I understood a higher number is more secure, but takes longer to calculate. Sometimes in fact a lot longer because 10 is not 10 rounds, but 2 to the power of 10. So going up from 10 to 11 can be 100’s of milliseconds increase in hash time (from what I’ve read it roughly doubles the hash calculation time each increment). This also means longer sign up and sign in times for password based accounts.

I started thinking what the 2 most important factors were for my use case:

  1. I want the highest value possible, but
  2. only if it doesn’t exceed a certain time threshold

This would provide the highest security, without agonizing wait times for users signing in.

After a couple days, I created bcrypt-salt to provide this solution. It can strengthen the bcrypt config in 2-3 lines.

I’m currently using it in one of my Meteor projects so thought I’d post an example here for anyone interested.

Install the package:

meteor npm install bcrypt-salt --save

Add this to a server only file:

import { Meteor } from "meteor/meteor";
import { Accounts } from "meteor/accounts-base";
import BcryptSalt from "bcrypt-salt";

Meteor.startup(() => {
  const bs = new BcryptSalt({ maxHashTime: 500, logs: true });
  Accounts._options.bcryptRounds = bs.saltRounds >= 10 ? bs.saltRounds : 10;

This calculates the highest saltRound within a given maxHashTime and sets Meteor (v1.6.1 or higher) Accounts._options.bcryptRounds to this value. If for some reason it is lower than 10, it sets the default 10.

For reference here are the logs returned on my MBP 2015 laptop:

saltRounds:  1, hashTime: 1.5116290000000845ms
saltRounds:  2, hashTime: 2.9353470000000925ms
saltRounds:  3, hashTime: 4.262208999999984ms
saltRounds:  4, hashTime: 5.647235000000137ms
saltRounds:  5, hashTime: 8.489819000000125ms
saltRounds:  6, hashTime: 13.52793900000006ms
saltRounds:  7, hashTime: 23.719949000000042ms
saltRounds:  8, hashTime: 43.463322999999946ms
saltRounds:  9, hashTime: 84.93861500000003ms
saltRounds: 10, hashTime: 159.71765900000014ms
saltRounds: 11, hashTime: 316.371854ms
saltRounds: 12, hashTime: 614.3531209999999ms

Recommended bcrypt saltRounds for this hardware is 11 running in 316.371854ms.

1 higher exceeds max hash time (500ms)

So I know I can use 11 without going over 500ms of hash calculation time (i.e. user sign in time).

500ms is provided as a default value. A time that is acceptable for each use case is subjective, so not meant as a recommendation. Each developer can set this to what works best for them.

Another use case is running the package as a utility to profile your server in different conditions (light load/heavy load) to find the optimal saltRounds for your app, then hard set this number.

In any case, thanks for reading. I’ve been a Meteor developer for about 4 years, this is my first npm package and grateful for any feedback.


you may be interested in BaaS