Many users have a small number of passwords -- often only one -- that they use everywhere. For their corporate domain account, their blog, their photo site, their email, their banking and PayPal accounts, and their discussion groups, one key opens them all. Despite the incredible risks involved with this practice, it is more prevalent than ever.
Password reuse is often the habit of jaded users who've been bitten by the "lost password" bug a few too many times, especially against sites that they seldom visit (or even frequently visited sites in cases where they've relied upon their browser or password utility to remember all of the variations...a hard drive crash or system migration leaves them helplessly flailing about, unable to access dozens of sites).
It's so much easier to remember one password than it is to remember dozens.
Of course, few will actually admit to recycling passwords like this, and instead it's the exceptions using unique 20 character random sequences that are most likely to speak out. Yet impromptu prodding of acquaintances, clients, and contacts, along with the results of several recent security surveys, has me convinced that these security best-practice aficionados are the exception, and a large number of users, perhaps even a majority, are dangerously reusing the same password prolifically.
If someone discovers your password on site A, there's a very good probability they can use it to access site B, and C, and D, and E, and so on. The security of your account relies upon the faith of a lot of people who you shouldn't have faith in, not to mention that it depends upon the weakest link before it all potentially unravels.
Despite all of the safeguards that I've put in place in the architecture and design of 360notes, I've tried to minimize the potential damage if an exploit ever did happen by eliminating any unnecessary information where possible (reducing the surface attack area). Following this philosophy, not only do I not want to store your password -- of course I only store a hash and not your original password, which should be a universal practice even among "low value" sites -- but I never want your probably-reused password ever hitting the site in the first place.
Instead of sending your password to be hashed on the server, I want it hashed on the client end, before it even gets sent down the wire.
This wouldn't be a possibility without JavaScript, however the functionality makes JavaScript pretty much mandatory, so in this case it's reasonable to require it for even the basic functionality of the site. As such, the account creation and logon system incorporates functionality that hashes a combination of your username, password, and the domain on the client end, passing through the hash to the server as your "password". As a secondary benefit, the server can generate single-use variants (salts of sorts) which it provides with the form. If such a variant is provided, after the client script has created the hash, it then hashes the first hash with the variant, which the server can do as well, offering basic line encryption as well presuming that the server is tracking the variants, and ensuring they are server provided and not reused (it doesn't replace SSL, so there is still avenues for man-in-the-middle attacks and untrusted remote servers masquerading as the official site, however it's a step in the right direction where SSL can't or won't be used).
The SHA1 algorithm is well known, and in this case I decided to go with the excellent SHA1 implementation by Paul Johnston. Implementing it was trivial, and a simple example demonstrating how to use it for this purpose follows.
<script language="JavaScript"
src="sha1.js" type="text/javascript"></script>
...
<form
name="loginForm" id="loginForm">
<input id="passwordHash" type="hidden" value="">
Email Address: <input id="emailAddress" type="text"
size="20"><br/>
Password: <input id="password" type="password"
size="20"><br/>
<input type=button onclick="DoLogon();" value="Logon"
/>
<input type=hidden id="variant" value="" />
</form>
<script language="JavaScript">
function DoLogon()
{
var domain = "www.360notes.com";
var username =
document.getElementById("emailAddress").value;
var password =
document.getElementById("password").value;
var hashString = domain +
"|" + username + "|" + password;
var hash = hex_sha1(hashString);
/* Variant - trivial "encryption" if the server has
provided
a tracked, single
use pseudo-salt. */
var variant =
document.getElementById("variant").value;
if (variant.length > 0)
{
hash = hex_sha1(hash + "|" + variant);
}
document.getElementById("passwordHash").value = hash;
/* Remove the password element from the form before
submitting */
document.getElementById("loginForm").removeChild(document.getElementById("password"));
/* Submit the form. */
document.loginForm.submit();
}
Voila. Now I never know that you use the password 4muppet8 on every site, and instead I only ever see a unique hash specific for this domain.
Of course this scheme still suffers a critical weakness: If, somehow, a nefarious agent could replace the server side scripts, and somehow my remote server validation scripts failed, they could simply alter it to pass through the original password. While that scenario is far more remote and unlikely than the already remote and unlikely database delving or line monitoring, it does demonstrate why the optimal situation would be intrinsic browser support: Instead of creating a site-specific custom script to secure and individualize the password for a specific domain, which allows users to reuse passwords without actually giving the password to any specific site, the browser should support this functionality directly, and it should be evident in the UI.
In addition to the password input type, there should be a secure password type (with obvious, non-spoofable graphical indicators that it is a secure pasword box) as a basic HTML element, automatically incorporating this sort of enhancement. HTTP already supports digest autentication, which is similar, but unfortunately it is incompatible with the form logon approach commonly used, not to mention that it has its own failings.