Password Generator using Sails.js
Was reading a piece on how a girl started a service of selling $2 cryptologically secure human memorizable passwords. This got me wondering on how she did it. Turns out she uses a dictionary of sorts where each five digit number corresponds to a word. So she will throw 5 dice and look up the word from the dictionary. Pretty awesome…
So here I started wondering if a software can do the same thing… I needed a fast way to develop it because I didn’t want spend too much time. I also wanted to create a REST API as a service for people that might want to plug this in to their own applications.
I decided to use NodeJS because I wanted to try out NodeJS version 5. Turns out it is pretty awesome with lots of new and cool utilities. But I digress…
I didn’t want to write too much stuff though. So I started looking for a framework to use. Sail.js got my attention because of the following paragraph:
Auto-generate REST APIs.
Sails comes with blueprints that help jumpstart your app’s backend without writing any code. Just run sails generate api dentist and you’ll get an API that lets you search, paginate, sort, filter, create, destroy, update, and associate dentists. Since these blueprint actions are built on the same underlying technology as Sails, they also work with Websockets and any supported database out of the box. –Sails.js
Turns out it was good choice for a weekend project. Creating a cool website has never been easier.
The important part of this API is it uses the Crypto library by NodeJS. So some sample code below for the controller part of the API.
/**
* PasswordgeneratorController
*
* @description :: Server-side logic for managing passwordgenerators
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
module.exports = {
generator:
function (req, res) {
var allowNumbers = req.param('allowNumbers');
var allowSymbols = req.param('allowSymbols');
var wordLimit = req.param('wordLimit');
var validator = require('validator');
var errors = [];
if (!validator.isBoolean(allowNumbers)) {
errors.push("allowNumbers must be boolean and is required.");
}
if (!validator.isBoolean(allowSymbols)) {
errors.push("allowSymbols must be boolean and is required.");
}
if (!validator.isInt(wordLimit, {min:1, max:1000})) {
errors.push("wordLimit must be a integer of minimum 1, maximum of 1000 and is required.");
}
if (errors.length > 0) {
return res.send( {"errors" : errors} );
}
var foundPerfectPassword = false;
var perfectPassword = sails.controllers.passwordgenerator.basePassword(validator.toInt(wordLimit),
validator.toBoolean(allowNumbers), validator.toBoolean(allowSymbols));
var password = {
"generated_password": perfectPassword
};
return res.send(password);
},
basePassword:
function (wordLimit, allowNumbers, allowSymbols) {
var dictionary = require('../models/dictionary.json');
var crypto = require('crypto');
var dieSides = "123456";
var numberOfThrows = 5;
var value = new Array(numberOfThrows);
var len = dieSides.length;
var wordIndex,
password = "",
tempPassword;
for (wordIndex = 0; wordIndex < (wordLimit); wordIndex++) {
var foundPerfectPassword = false;
while (!foundPerfectPassword) {
var rnd = crypto.randomBytes(numberOfThrows)
for (var i = 0; i < numberOfThrows; i++) {
value[i] = dieSides[rnd[i] % len];
};
var key = value.join('');
tempPassword = dictionary[key];
foundPerfectPassword = true;
if (!allowNumbers) {
var regexSymbolAndChar = /^[A-Za-z-\s-!$%^&*()_+|~=`{}\[\]:";'<>?,@#.\/]+$/;
if(!regexSymbolAndChar.test(tempPassword)){
foundPerfectPassword = false;
} else {
foundPerfectPassword = true;
}
}
if (foundPerfectPassword && !allowSymbols) {
var regexNumberAndChar = /^[A-Za-z-\s-1234567890]+$/;
if(!regexNumberAndChar.test(tempPassword)){
foundPerfectPassword = false;
} else {
foundPerfectPassword = true;
}
}
}
//wanted to add more complexity
var firstOrLastRandomNumber = crypto.randomBytes(1);
if (firstOrLastRandomNumber[0] % 2){
if (password != "") {
password = tempPassword + " " + password;
} else {
password = tempPassword;
}
} else {
if (password != "" ) {
password = password + " " + tempPassword;
} else {
password = tempPassword;
}
}
}
return password.trim();
}
};
The important part is the usage of crypto.randomBytes which allows us to develop random numbers.
Oh and one more thing you can find the site : https://bloodcurdling-fangs-2095.herokuapp.com/
You can find the code @ https://github.com/JohnRoach/PasswordGenerator
Have fun!