Using openssl_random_pseudo_bytes() to generate a strong random string in PHP

December 27th 2012

In PHP, there's a great method called openssl_random_pseudo_bytes() which according to PHP.net:

'Generates a string of pseudo-random bytes, with the number of bytes determined by the length parameter.'

I use strings to temporarily encrypt information to be passed with a form request to assist the detection of a user playing with the form values.

Generating a random string is quite like my class to generate a random password:

You can read about generating random passwords here

Anyway, using the openssl_random_pseudo_bytes() method, I've put this class together to allow for the dynamic generation of strong random strings.

PHP Code:
<?php
class App_Cryptography_Random {

    
/**
     * Generates binary data into hexadecimal representation
     * as a random string utilising openssl_random_pseudo_bytes
     * @param integer $targetLength
     * @return string
     */
    
public static function getRandomString($targetLength 40) {

        if (!
is_numeric($targetLength))
        {
            
trigger_error("targetLength specified for App_Cryptography_Random should be numeric, using default of 40 length.");
            
$targetLength = (int)40;
        }
        else
        {
            
$targetLength = (int)$targetLength;
        }

        if (!
is_integer($targetLength))
        {
            
trigger_error("targetLength specified for App_Cryptography_Random should be an integer, using default of 40 length.");
            
$targetLength 40;
        }

        for (
$i = -1$i <= ($targetLength 4); $i++) {
            
$bytes openssl_random_pseudo_bytes($itrue);
            
$hex   bin2hex($bytes);
            if (
strlen($hex) == $targetLength)
            {
                break;
            }
        }
        return 
$hex;
    }

}

Using the class is easy, call it with:

PHP Code:
<?php
$random 
App_Cryptography_Random::getRandomString(40);

Of course, you can replace the 40 with almost any size integer, but I've only tested this up to 2048.

If this helps you out, let me know in the comments.