reptile7's JavaScript blog
Sunday, November 03, 2013
 
The Password Factory
Blog Entry #305

In today's post we will discuss a "Make Me A Password" script that generates variable-length, random-character passwords for use on the Web. The "Make Me A Password" script was authored by Bill "Ace" Frederickson in 1998 and was part of the Scripts that Display Text collection of Joe Burns' late-1990s Java Goodies JavaScript Repository project.

You can grab Ace's script here; try it out here. The script does have one little glitch: in practice it occasionally produces a password that is one or two characters shorter than it should be. As we'll see below, correcting this glitch is nothing more complicated than changing a Math.round( ) command to a corresponding Math.floor( ) command.

The script interface

The script's interface comprises three controls - in order, a Length of Password : text box, a push button, and a Random Password : text box - held by a frmPw form.

<body>
<form name="frmPw">
Length of Password : <input type="text" name="txtMax" size="5" value="8"><br>
<input type="button" value="Pick Random Password" onclick="rndPw( );")><br>
<font size="+1">Random Password : <input type="text" name="txtRandpw" size="20" value=""></font>
</form>


The form container is semantically inappropriate in the sense that we won't be submitting any data to a processing agent, but it had to be there for the browser to render the inputs back in the day; today we would wrap the inputs and labels in a div.

If you want to hold onto the form container and plan to validate your document, then you should be aware that the form element has different content models in the Strict and Transitional DTDs.
(S) In the Strict DTD, the form element's content model is (%block;|SCRIPT)+ -(FORM), which the above code violates. If you go through the form examples in the Forms chapter of the HTML 4.01 Specification, you'll notice that in each case the control content is wrapped in a p element, which seems redundant to me in that the form and p elements are both width=100% %block; elements, although I'm sure that the W3C had a good reason for doing things this way.
(T) In the Transitional DTD, the form element's content model is (%flow;)* -(FORM), which the above code conforms to.

The Length of Password : and Random Password : labels can and should be marked up as label elements.

The <font size="+1"> … </font> markup is not quite equivalent to a font-size:larger; style declaration: the former takes a 16px font size to 18px whereas the latter takes a 16px font size to 19px. (Where else but at reptile7's JavaScript blog would you learn this crucial information? ;-)) Is it really necessary to make the Random Password : label larger than the Length of Password : label? Nope, lose the font element.

Lastly and least, the ) right parenthesis character at the end of the button's input element doesn't cause any problems but shouldn't be there - take it out.

Script operation

Clicking the button calls a rndPw( ) function in the document head. The rndPw( ) function generates a random-character password and loads it into the Random Password : field; the length of the password is set by the value of the Length of Password : field.

The rndPw( ) function first defines a series of variables:

function rndPw( ) { var iStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; var n = 0; var i = 0; var s = ""; len = document.frmPw.txtMax.value; … }

• The 26 uppercase A-Z alphabetic characters and the 26 lowercase a-z alphabetic characters and the 10 0-9 digit characters are loaded into a single string, which is given an iStr identifier; as you would intuit, the password characters will be drawn from the iStr string. You could add ASCII's symbolic characters (~, !, @, etc.) to the iStr string if you wanted to but it is probably best to stick with alphanumeric characters here.

• The n and i variables will be used to index-wise source the individual characters of the password, and are initialized to 0.

• The password will be assembled/stored in an s variable, which is initialized to an empty string.

• The value of the Length of Password/txtMax field is assigned to a len variable.

Next, a len-iteration for loop creates the password:

for (x = 1; x <= len; x++) { n = Math.random( ) * 62; i = Math.round(n); s += iStr.charAt(i); }

The n = Math.random( ) * 62; line calculates a random floating-point number (running many places past the decimal point) in the range 0 (inclusive) to 62 (exclusive) and assigns it to n; read about the random( ) method of the Math object here.

The i = Math.round(n); line rounds n up or down to the nearest integer, to which i is set; read about the round( ) method of the Math object here.

The s += iStr.charAt(i); line gets the ith character in the iStr string and appends it to s's value; read about the charAt( ) method of the String object here.

(We've encountered random( ), round( ), and charAt( ) many times previously, but given that Mozilla apparently does not subscribe to Tim Berners-Lee's "Cool URLs don't change" philosophy, I thought I would give you some updated references.)

The iStr string comprises 62 characters and its character index therefore runs from 0 to 61. If i is 62 (if n61.5), then iStr.charAt(i) returns an empty string and nothing is added to s. To ensure a len-character password, replace Math.round(n) with Math.floor(n), whose maximum return will be 61; read about the floor( ) method of the Math object here.

After len random iStr characters have been loaded into s, the rndPw( ) function finally assigns s to the value of the Random Password/txtRandpw field:

document.frmPw.txtRandpw.value = s;

Demo




The default password length is 8 although the Length of Password : field's value can be legitimately set to any positive integer*; as a practical matter, however, I wouldn't go any higher than 15.
*It is left to the reader to add to the rndPw( ) function validation code that flags other input types: floating-point numbers, 0, etc.

Some password-soliciting Web sites recommend or require that user passwords contain at least one uppercase letter, at least one lowercase letter, and at least one digit; you may need to click the button a few times to get a password that meets these criteria.

N.B. I apply the Verdana typeface to the password because, unlike some other common fonts, Verdana renders distinctively the uppercase I letter, the lowercase l letter, and the 1 digit.

And there you have it - a very simple script that does something genuinely useful. Password away!

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)