Kapn0batai
Kapn0batai

Reputation: 215

Random string generator

I have to generate a random string with a fixed length of 10 characters. But the trick is that it must contain at least one lowercase letter, one uppercase one, a digit and one of these symbols: `~!@#$%^&*()_-+={}[]|:;"'<>,.?/

I used this simple function before:

function generateRandomString($length = 10)
{
    $characters='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ`~!@#$%^&*()_-+={}[]|:;"\'<>,.?/';
    $result = '';
    for ($i = 0; $i < $length; $i++)
        $result .= $characters[rand(0, strlen($characters) - 1)];
    return $result;
}

But this function doesn't include at least one of each character type needed. Even if I go another route:

function generateRandomString($length = 10)
{
    $dig = '0123456789';
    $low = 'abcdefghijklmnopqrstuvwxyz';
    $upp = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $sym = '`~!@#$%^&*()_-+={}[]|:;"\'<>,.?/';
    $result = '';

    for ($i = 0; $i < $length; $i++)
    {
       $foo = rand(1,4);
       switch ($foo)
       {
           case 1:
               $result .= $dig[rand(0, strlen($dig)-1)];
               break;
           case 2:
               $result .= $low[rand(0, strlen($low)-1)];
               break;
           // etc.
       }
        return $result;
    }

This still wouldn't necessarily contain at least one of each. All the characters must be randomly placed. So any help would be much appreciated. Thank you.

Upvotes: 1

Views: 337

Answers (3)

Beat
Beat

Reputation: 1380

If your generator doesn't need to be very fast, you could do something like this:

do {
    $string = generateRandomString(10);
} while(!check_password_rules($string))

function check_password_rules($string) {
    // return true if password fits policy
}

It has the advantage that you don't sacrifice any randomness by setting fixed probabilities for character groups.

Upvotes: 2

Justin
Justin

Reputation: 458

You can build your list and then use str_shuffle. I'm sure this can be simplified and written a bit better, but this works.

I added a percentage method so you can have a certain percentage of each characters.

function generateRandomString($length = 10) {
    $result = getRandomString(.2 * $length, '0123456789');
    $result .= getRandomString(.3 * $length, 'abcdefghijklmnopqrstuvwxyz');
    $result .= getRandomString(.3 * $length, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
    $result .= getRandomString(.2 * $length, '`~!@#$%^&*()_-+={}[]|:;"\'<>,.?/');

    $str_len = strlen($result);
    if($str_len != $length) $result .= getRandomString($length - $str_len, 'abcdefghijklmnopqrstuvwxyz');

    return str_shuffle($result);
}

function getRandomString($length, $characters) {
    $result = '';
    $strlen = strlen($characters);
    for($i = 0; $i < floor($length); $i++) $result .= $characters[rand(0, $strlen - 1)];

    return $result;
}

echo generateRandomString(31);

Upvotes: 2

NG.
NG.

Reputation: 22904

I don't quite know PHP, but I imagine you could do something like this (forgive syntax errors):

$result = "";
$result .= $dig[rand(0, strlen($dig) - 1];
$result .= $low[rand(0, strlen($low) - 1];
$result .= $upp[rand(0, strlen($upp) - 1];
$result .= $sym[rand(0, strlen($sym) - 1];

// at this point, you have one of each
// Go through your for loop 6 more times, and then finally:

$result = str_shuffle($result)

Hope that helps. str_shuffle seems like it would be useful.

Upvotes: 5

Related Questions