How-to create a Password Generator using PHP

Do you need a password generator function for your user registration application or do you have to write a script in PHP? Than is this PHP tutorial for you. The function in this guide is flexible enough to use it during the user registration process or for a password recovery function. The generated password from this function is so safe as you which: Generate alpha-numerical password combined with capital character or with special signs or characters. All used character are based on the number from the ASCII table.

In this tutorial we will explain all the important code, find the complete function at the begin of this tutorial. We used the tutorial code also for our Google Gadget, you can try it just by adding the gadget to your iGoogle start page.

The PHP code for the function

function create_password($pw_length = 8, $use_caps = true, $use_numeric = true, $use_specials = true) {
	$caps = array();
	$numbers = array();
	$num_specials = 0;
	$reg_length = $pw_length;
	$pws = array();
	for ($ch = 97; $ch <= 122; $ch++) $chars[] = $ch; // create a-z
	if ($use_caps) for ($ca = 65; $ca <= 90; $ca++) $caps[] = $ca; // create A-Z
	if ($use_numeric) for ($nu = 48; $nu <= 57; $nu++) $numbers[] = $nu; // create 0-9
	$all = array_merge($chars, $caps, $numbers);
	if ($use_specials) {
		$reg_length =  ceil($pw_length*0.75);
		$num_specials = $pw_length - $reg_length;
		if ($num_specials > 5) $num_specials = 5;
		for ($si = 33; $si <= 47; $si++) $signs[] = $si;
		$rs_keys = array_rand($signs, $num_specials);	
		foreach ($rs_keys as $rs) {
			$pws[] = chr($signs[$rs]);
		}
	} 
	$rand_keys = array_rand($all, $reg_length);
	foreach ($rand_keys as $rand) {
		$pw[] = chr($all[$rand]);
	}	
	$compl = array_merge($pw, $pws);	
	shuffle($compl);
	return implode('', $compl);
}

We create a for loop to build our arrays with characters, while the default characters are always included, we use if statements to include the capital or numeric characters.

	for ($ch = 97; $ch <= 122; $ch++) $chars[] = $ch; // create a-z
	if ($use_caps) for ($ca = 65; $ca <= 90; $ca++) $caps[] = $ca; // create A-Z
	if ($use_numeric) for ($nu = 48; $nu <= 57; $nu++) $numbers[] = $nu; // create 0-9

After this, we merge the three arrays together into one array called $all:

	$all = array_merge($chars, $caps, $numbers);

If the function is configured to use special characters, we use 25% from the password length for these characters. Next we check the number of used special character, if we reach 5 of them (based on the 25% from the password length) we replace the value with 5.

		$reg_length =  ceil($pw_length*0.75);
		$num_specials = $pw_length - $reg_length;
		if ($num_specials > 5) $num_specials = 5;

As before we use a for loop to create the array with special characters. We use the array_rand function to create another array with random keys and the foreach loop will add the values to the array $pws.

		for ($si = 33; $si <= 47; $si++) $signs[] = $si;
		$rs_keys = array_rand($signs, $num_specials);
		foreach ($rs_keys as $rs) {
			$pws[] = chr($signs[$rs]);
		}

With the same method as for the special characters we will build the array $pw using the alpha-numerical array.

	$rand_keys = array_rand($all, $reg_length);
	foreach ($rand_keys as $rand) {
		$pw[] = chr($all[$rand]);
	}

The next code will merge the two password arrays and after we used the function shuffle before the password is returned as a string (using the implode function).

	$compl = array_merge($pw, $pws);	
	shuffle($compl);
	return implode('', $compl);

With function it’s very easy to create a random password in your application, just use it this way:

$password = create_password(12, false, true, false); // creates 12 character alpha-numeric password

What do you think what could be better? Maybe we can segment the amount of numbers or capitals? If you like to use less different characters, just decrease the numbers inside the for loops. Use this ASCII table as your reference. Please post your comments below or open a thread on our PHP forum at finalwebsites.com.

 

Related posts

Comments

Trackback URL for this post: http://www.web-development-blog.com/archives/how-to-create-a-password-generator-using-php/trackback/

Good code, but those ‘for’ cycles look like they’re not in place :) For letters, you can use range(‘a’,'z’); and range(‘A’,'Z’);, then for ’specials’ the cycle could be placed with range(33,47);, same with numbers. They will create array’s with the needed symbols :) It’s more practical, and it looks cleaner, and of course the performance SHOULD be better :)

Hi fosron,

Thanks for the comment, it’s funny I’m sure that I noticed that function before, but never used it :D

I don’t think that most of the websites will see a big raise in performance. But for those this is the function in a more “compact” format:

function create_password($pw_length = 8, $use_caps = true, $use_numeric = true, $use_specials = true) {
	$caps = array();
	$numbers = array();
	$num_specials = 0;
	$reg_length = $pw_length;
	$pws = array();
	$chars = range(97, 122); // create a-z
	if ($use_caps) $caps = range(65, 90); // create A-Z
	if ($use_numeric) $numbers = range(48, 57); // create 0-9
	$all = array_merge($chars, $caps, $numbers);
	if ($use_specials) {
		$reg_length =  ceil($pw_length*0.75);
		$num_specials = $pw_length - $reg_length;
		if ($num_specials > 5) $num_specials = 5;
		$signs = range(33, 47);
		$rs_keys = array_rand($signs, $num_specials);	
		foreach ($rs_keys as $rs) {
			$pws[] = chr($signs[$rs]);
		}
	} 
	$rand_keys = array_rand($all, $reg_length);
	foreach ($rand_keys as $rand) {
		$pw[] = chr($all[$rand]);
	}	
	$compl = array_merge($pw, $pws);	
	shuffle($compl);
	return implode('', $compl);
}

Or, simply:
$ pear install Text_Password
and then in your code:
require_once ‘Text/Password.php’;
echo Text_Password::create();

Hi Christian,

sure there are many options. I don’t like PEAR ;)
Don’t forget many shared hosting provider doesn’t allow pear installs

You don’t have to have a hosting provider’s permission to use PEAR packages (hint: they work without PEAR installer).
As for the code, how about something like this:

function randomString($length = 16)
{
$alhpabet = ''ABCDEFGHIJKLMNOPORRQSTUWVXYZabcdefghijklmnoprqstuwvxyz0123456789!@#$%^&*?';
$alphabetLenght = strlen($alphabet) - 1;
$string = '';
while($length) {
$string .= $alphabet[mt_rand(0, $alphabetLenght)];
--$length;
}
return $string;
}

For a “special symbols in 25% of the password” thing you would have to have a separate variable for those special symbols and then in the loop something like this:

if (mt_rand(0,3)) {
$string .= $alphabet[mt_rand(0, $alphabetLenght)];
} else {
$string .= $specialSymbols[mt_rand(0, strlen($specialSymbols))];
}

That won’t guarantee you perfect 25% every time, but statistically it should oscillate around that number (gotta love math!) and it’s much more elegant solution I think.

Correction of some errors I’ve made:
- it should be “strlen($specialSymbols) – 1″
- $alphabet instead of $alhpabet in the 1st line of the function
- there is a “‘” repeated with the $alphabet declaration

Hallo Tomek,

First of all thank for posting your code example.

Why not using PEAR?

Sure your can download all classes from the pear site.
I think the best is the PEAR distribution system, why should I use PEAR? Because there are so many old projects? yes there are some good projects but how do I know as which are good? If I need to use some “library” I go for the Zend Framework.

About your function, I used this kind of code very often (short and simple), but you see that my function has much more control about which character I can use.

Don’t forget this tutorial is supposed to show things work ;)

Thanks for sharing a code sample, but please don’t teach people to use bad coding style. Omitting braces is a recipe for disaster here:

if ($use_caps) for ($ca = 65; $ca <= 90; $ca++) $caps[] = $ca; // create A-Z

Also, the way of specifying options can get awkward. A bit mask is more elegant here:

function create_password($options) {
  if ($options & PASSWORD_USE_SPECIALS) {
    /* ... */
  }
}

And as said before, don't reinvent the wheel. :-)

Hi Jan,

Normally I use braces in my code, but for tutorials I try to keep the code as short as possible … :)

I don’t understand your second comment, do you suggest to use an array for the options? Why do you suggest a constant variable?
Try the Google gadget to see why I used multiple filters/switches as arguments.

Nice script. Thanks

I have one concern with it (sorry, I’m going to be a little bit blunt), but the syntax you use is atrocious and disgusting:

if ($use_numeric) for ($nu = 48; $nu < = 57; $nu++) $numbers[] = $nu;

This is acceptable though:

if ($use_numeric) $numbers = range(48, 57);

but this is better:

if ($use_numeric)
$numbers = range(48, 57);

Code readability is very important...

Sorry for the double post. In the line of code after “but this is better:” the line: “$numbers = range(48, 57);” should have been indented in my last comment…

Hello Aziz,
you’re right readability is important, but is also about personal “coding style” ;)
I see a lot of people coding this way:

if ($val) 
{
    echo 'Hello!';
}

This is something I don’t like.
Right my IF statement with a FOR loop on a single row without using braces is very short, but I can read this very well:
if ($use_numeric) $numbers = range(48, 57);

btw. You see that Wordpress gives a new format to posted code as well.

Hello Olaf,

You are right. if we use the single row without using braces like if ($use_numeric) $numbers = range(48, 57);
is very short. but the beginners can’t able to understood it at first look.

@srisoftwarez,
I remember me that I had some problems (years ago with notations like:

$var ($is_true) ? 'cool' : 'not cool';

But if you need to pass only one value to a variable , it should be fine to use these short notations. If I have 10 statements like this I can choose from 10 rows I need to scroll or 40

Sorry, the comment form is closed at this time.