Generating Random Passwords in JavaScript

The JavaScript program below allows the user to generate a pseudo-random password using a specified length and character types. To see it in action, copy it into a web browser that runs JavaScript. Or, for an online version, visit https:thiscouldbebetter.neocities.org/randompasswordgenerator.html.

Note that most cryptographic professionals would not consider JavaScript’s pseudo-random number generator “random enough” to produce cryptographically secure passwords. But in practice, this approach is probably good enough for most applications short of securing a global financial conglomerate or a nuclear submarine. Still, adding a little extra randomness through some other process might not be a bad idea.

passwordgenerator


<html>
<body>
 
<!-- ui -->
 
	<div>
		<label>Number of Characters:</label>
		<input id="inputNumberOfCharacters" type="number" value="12"></input>
	</div>
 
	<div>
		<label>Characters Allowed:</label>
 
		<label>Uppercase:</label>
		<input id="checkboxUppercase" type="checkbox" checked="true"></input>
 
		<label>Lowercase:</label>
		<input id="checkboxLowercase" type="checkbox" checked="true"></input>
 
		<label>Numerals:</label>
		<input id="checkboxNumerals" type="checkbox" checked="true"></input>
	 
		<label>Punctuation:</label>
		<input id="inputPunctuation" value="+/"></input>

		<label>Enforce One or More of Each Type:</label>
		<input id="checkboxOneOfEach" type="checkbox" checked="true"></input>

	</div>
 
	<div>
		<button onclick="buttonPasswordGenerate_Clicked();">Generate</button>
	</div>
	 
	<div>
		<label>Password Generated:</label>
		<input id="inputOutput"></input>
	</div>
 
<!-- ui ends -->
 
<script type="text/javascript">
 
// ui event handlers
 
function buttonPasswordGenerate_Clicked()
{
	var inputNumberOfCharacters = 
		document.getElementById("inputNumberOfCharacters");
	var numberOfCharactersAsString = inputNumberOfCharacters.value;
	var numberOfCharacters = parseInt(numberOfCharactersAsString);
 
	var checkboxUppercase = 
		document.getElementById("checkboxUppercase");
	var areUppercaseLettersAllowed = checkboxUppercase.checked;
 
	var checkboxLowercase = 
		document.getElementById("checkboxLowercase");
	var areLowercaseLettersAllowed = checkboxLowercase.checked;
 
	var checkboxNumerals = 
		document.getElementById("checkboxNumerals");
	var areNumeralsAllowed = checkboxNumerals.checked;
 
	var inputPunctuation = 
		document.getElementById("inputPunctuation");
	var punctuationCharactersAllowed = inputPunctuation.value;

	var checkboxOneOfEach = 
		document.getElementById("checkboxOneOfEach");
	var enforceOneOrMoreOfEachCharacterType = checkboxOneOfEach.checked; 
	
	var passwordGenerated = passwordGenerate
	(
		numberOfCharacters, 
		areUppercaseLettersAllowed,
		areLowercaseLettersAllowed,
		areNumeralsAllowed,
		punctuationCharactersAllowed,
	enforceOneOrMoreOfEachCharacterType 
	);
	 
	var inputOutput = document.getElementById("inputOutput");
	inputOutput.value = passwordGenerated;
}
 
// main
 
function passwordGenerate
(
	numberOfCharactersInPassword, 
	areUppercaseLettersAllowed,
	areLowercaseLettersAllowed,
	areNumeralsAllowed,
	punctuationCharactersAllowed,
	enforceOneOrMoreOfEachCharacterType 
)
{

	var characterSetsToUse = [];	
 
	if (areUppercaseLettersAllowed == true)
	{
		var charactersUppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		characterSetsToUse.push(charactersUppercase);
	}
 
	if (areLowercaseLettersAllowed == true)
	{
		var charactersLowercase = "abcdefghijklmnopqrstuvwxyz";
		characterSetsToUse.push(charactersLowercase);
	}
 
	if (areNumeralsAllowed == true)
	{
		var charactersNumerals = "0123456789";
		characterSetsToUse.push(charactersNumerals);
	}
 
	if (punctuationCharactersAllowed.length > 0)
	{
		characterSetsToUse.push(punctuationCharactersAllowed);
	}

	var charactersAllowed = "";

	for (var i = 0; i < characterSetsToUse.length; i++)
	{
		var characterSet = characterSetsToUse[i];
		charactersAllowed += characterSet;
	}
 
	var passwordSoFar = "";
 
	for (var i = 0; i < numberOfCharactersInPassword; i++)
	{
		var characterNextIndex = Math.floor
		(
			Math.random() * charactersAllowed.length
		);
 
		var characterNext = charactersAllowed[characterNextIndex];
 
		passwordSoFar += characterNext;
	}

	if (enforceOneOrMoreOfEachCharacterType == true)
	{
		passwordSoFar = passwordGenerate_EnforceOneOrMoreOfEachCharacterType
		(
			characterSetsToUse,
			passwordSoFar
		);
	}

	return passwordSoFar;
}

function passwordGenerate_EnforceOneOrMoreOfEachCharacterType
(
	characterSetsToUse, passwordSoFar
)
{
	var characterCountsBySet = [];

	for (var j = 0; j < characterSetsToUse.length; j++)
	{
		var characterSet = characterSetsToUse[j];

		var charactersInSetSoFar = 0;

		for (var i = 0; i < passwordSoFar.length; i++)
		{
			var characterToTest = passwordSoFar[i];

			var isCharacterInSet = 
				(characterSet.indexOf(characterToTest) >= 0);

			if (isCharacterInSet == true)
			{
				charactersInSetSoFar++;
			}
		}

		characterCountsBySet.push(charactersInSetSoFar);
	}

	var charactersToSubstituteIn = [];

	for (var i = 0; i < characterCountsBySet.length; i++)
	{
		var numberOfCharactersBelongingToSet = 
			characterCountsBySet[i];

		if (numberOfCharactersBelongingToSet == 0)
		{
			var characterSet = characterSetsToUse[i];
			var charIndexRandom = Math.floor
			(
				Math.random() * characterSet.length
			)
			var charToSubstituteIn = characterSet[charIndexRandom];
			charactersToSubstituteIn.push(charToSubstituteIn);
		}
	}


	for (var i = 0; i < charactersToSubstituteIn.length; i++)
	{
		var characterToSubstituteIn = charactersToSubstituteIn[i];

		var indexToSubstituteAt = null;

		var jInitial = Math.floor
		(
			Math.random() * passwordSoFar.length
		);

		var j = jInitial;

		while (indexToSubstituteAt == null)
		{
			var charToSubstituteOut = passwordSoFar[j];

			for (var k = 0; k < characterSetsToUse.length; k++)
			{
				var characterSet = characterSetsToUse[k];

				var doesCharBelongToSet = 
					(characterSet.indexOf(charToSubstituteOut) >= 0);

				if (doesCharBelongToSet == true)
				{
					var numberOfCharactersOfType = 
						characterCountsBySet[k];

					if (numberOfCharactersOfType > 1)
					{
						numberOfCharactersOfType--;

						characterCountsBySet[k] = 
							numberOfCharactersOfType;

						indexToSubstituteAt = j;

						break;
					}
				}
			}
				
			j++;
			if (j >= passwordSoFar.length)
			{
				j = 0;
			}
			else if (j == jInitial)
			{
				break;
			}
		}

		if (indexToSubstituteAt == null)
		{
			alert("Not enough characters to include required types.");
		}

		passwordSoFar = 
			passwordSoFar.substr(0, indexToSubstituteAt)
			+ characterToSubstituteIn
			+ passwordSoFar.substr(indexToSubstituteAt);
	}

	return passwordSoFar;
}
 
 
</script>
</body>
</html>

Advertisements
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s