Login Credentials Generator – in JavaScript

Many small applications need to store user credentials, but it's hard to create a good username/password infrastructure. What if you could just use a small XML file with credentials that don't actually stores the password, but just a hash and some salt.

For a small cloud project I ended up creating such a solution. This blog explains how to generate the credentials that can be stored in the XML. The aim is to make a solution that works on the client using JavaScript.

Program

The program looks like this:

Techniques

In this solution we use the following techniques:

  • Hashing - a hash is a mathematical function that will turn a plain-text into a huge number. If one of the letters in the plain-text is changed, the hash changes. If a user gives us a password, we can hash that password and compare it to the hash we have. Not storing the password makes your user data more secure.
  • Salt - some attackers will use a rainbow table attack. They have huge table with plain-texts and their hashes. To mitigate this attack, we'll generate salt and add it to the plain-text that will be hashed. In our case the plain-text will be 40 characters long. It's hard to generate a rainbow table for it.
  • SHA256 - is the hash function we will use. It generates a 32-bit hash.

Frameworks

Never code what you don't need. I used the following JavaScript frameworks to make coding easier:

  • JQuery - always makes life easier
  • Knockout JS - a framework to bind a model to the DOM
  • Crypto-JS - a small solution that helps to generate SHA256 hashes.

I'm using a CDN to get the includes:

<script src="//code.jquery.com/jquery-compat-git.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/sha256-min.js"></script>

A string randomizer

We need a randomizer to create salt and generate passwords. We’ll be using the following function:

var randomString = function (length, nonAlpha) {
  var text = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

  if (nonAlpha) {
    possible += '[email protected]#$%^*()/*`~={}|\][;:,./?';
  }

  for (var i = 0; i < length; i++) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
  }

  return text;
}

If we use this function to generate salt, we should generate longer salt, because the entropy of the JavaScript generator isn’t that great.

A model

Let’s create a model . It will be the heart of the application:

var PasswordModel = function () {

  var _this = this;
  this.userName = ko.observable('');
  this.password = ko.observable('');
  this.roles = ko.observable('');

  this.salt = ko.computed(function () {
    //generate new salt on password/username update
    var u = _this.userName();
    var p = _this.password();
    return randomString(24, true);
  });

  this.hash = ko.computed(function () {
    var h = _this.salt() + _this.password();
    return CryptoJS.SHA256(h);
  });

  this.xml = ko.computed(function () {

    var xml = $('<user />');
    xml.attr('name', _this.userName());
    xml.attr('roles', _this.roles());
    xml.attr('salt', _this.salt());
    xml.attr('hash', _this.hash());

    return xml.wrap('<div/>').parent().html();
  });

  //generate a new alpha-numeric password
  this.generateNewPassword = function () {
    var password = randomString(16, false);
    _this.password(password);
  };

  this.generateNewPassword();
}

A user interface

Next we'll need to create a simple user interface and let Knockout do the rest:

<div class="row">
  <label>
    <span>Username:</span>
    <input data-bind="value: userName, valueUpdate: 'afterkeydown'" class="value" autocomplete="off" />
  </label>
</div>
<div class="row">
  <label>
    <span>Password:</span>
    <input data-bind="value: password, valueUpdate: 'afterkeydown'" class="value" autocomplete="off" />
  </label>
</div>
<div class="row">
  <label>
    <span />
    <button type="checkbox" data-bind="click: generateNewPassword">Generate new password</button>
  </label>
</div>
<div class="row">
  <label>
    <span>Roles:</span>
    <input data-bind="value: roles, valueUpdate: 'afterkeydown'" class="value" />
  </label>
</div>
<div class="row">
  <label>
    <span>XML:</span>
    <code data-bind="text: xml" class="value" />
  </label>
</div>

Knockout binding:

$(document).ready(function () {
	var model = new Model();
	ko.applyBindings(model);
});

Wrap-up

So that's it. It's quite easy to make and host yourself, check GitHub. But you're always welcome to use my generator: KeesTalksTech Password Generator.

expand_less