How to generate random password like WordPress using PHP?

WordPress Blogging Engine is a champion in a lot of way. One of the unique thing which you might have noticed is the random password generated by the wordpress, in case you try to generate a new password. Here are a few examples:

  • j0LH(WM9b_-q
  • wr^sqct1cmff
  • )P4-e531#-aL

Lets have a look at the code which can generate such random passwords for us. Later on we will dig deep into the code to understand each and every bit of it:

<?php

  class utility {

    static $random = '';

    // generates a random password
    // By default of length 12 having special characters
    static function generate_password($length = 12, $special_chars=true) {
      $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
      if($special_chars) $chars .= '!@#$%^&*_-()';

      $password = '';
      for($i=0; $i<$length; $i++)
        $password .= substr($chars, self::generate_random_number(0, strlen($chars)-1), 1);
      return $password;
    }

    // generates a random number between $min and $max
    static function generate_random_number($min=0, $max=0) {
      // generate seed. TO-DO: Look for a better seed value everytime
      $seed = mt_rand();

      // generate $random
      // special thing about random is that it is 32(md5) + 40(sha1) + 40(sha1) = 112 long
      // hence if we cut the 1st 8 characters everytime, we can get upto 14 random numbers
      // each time the length of $random decreases and when it is less than 8, new 112 long $random is generated
      if(strlen(self::$random) < 8 ) {
        self::$random = md5(uniqid(microtime().mt_rand(), true).$seed);
        self::$random .= sha1(self::$random);
        self::$random .= sha1(self::$random.$seed);
      }

      // take first 8 characters
      $value = substr(self::$random, 0, 8);

      // strip first 8 character, leaving remainder for next call
      self::$random = substr(self::$random, 8);

      $value = abs(hexdec($value));
      // Reduce the value to be within the min - max range. 4294967295 = 0xffffffff = max random number
      if($max != 0) $value = $min + (($max - $min + 1) * ($value / (4294967295 + 1)));
      return abs(intval($value));
    }

  }

  // print new random password
  echo utility::generate_password();

?>

Lets dig into the code
static function generate_password($length=12, $special_chars=true) is a static method of our utility class. It accepts two parameters. $length who’s default value is 12 and $special_chars who’s default value is true. By turning on $special_chars, our random generated password will include characters like !@#$%^&*_-()

static function generate_random_number($min=0, $max=0) is yet another static function of the utility class. It generates random number between $min and $max, the two parameters which can be passed. Default value for both is 0. However internally, generate_random_number() do a lot of trick to get us some really random numbers.

Algorithm
generate_random_number() works with following variables:

  1. $seed: which is equal to mt_rand()
  2. self::$random is a static variable. To start with this variable equals to ” (nothing). generate_random_number() checks for the length of self::$random. If its length is < 8, it generates a new 112 character long random value (see the code above) and assign it to self::$random. From here on, every time a random number is requested, it uses a chunks of 8 characters from the starting of self::$random, which is then used to generate a random number (see the code above). After each iteration length of self::$random decreases by 8. Because self::$random is 112 characters long, we can use it 14 times to get a random number (14×8 = 112).
  3. $value is the actual 8 digit character extracted from the starting of self::$random, which is later on processed to generate a random number between $min and $max values.

Further these methods can also be used to generate short url’s like tinyurl.com or bit.ly.