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 += '_+-!@#$%^*()/*`~={}|\][;:,./?';
}
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.