Random Token Generator

By Typo on Mar 06, 2014

Generate random strings (tokens) of variable lengths with selectable characters and output
in text, binary, octal, decimal or hexadecimal.

    By default the function uses what I will refer to as standard and special printable ASCII
    characters.  The standard characters are a-z, A-Z and 0-9.  The special characters are
    ! " # $ % ^ ' ( ) * + , - . / ; ; < = > ? @ [ \ ] ^ _ `

    To understand why I did this, here is one of the many articles available 
    explaining the weaknesses in PHP's randomization functions.
    http:  phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random-Values.html

    My solution was simply to rely on the SSH random byte function, converting the returned 
    random byte into decimal and making sure it falls in my range of desired characters.
    This leverages both the added security of the SSH randomization and additionally makes
    the amount of loops which will be used to build the string impossible to predict thereby
    reducing the chance of any possible successful attack on the token.

    You can define the length of the string to return (pre base conversion) or the default is 64.

    You can optionally select the base of the output. (If unsure, use False or 5).  Valid options
    are 1 for Binary, 2 for Octal, 3 for Decimal, 4 for Hexidecimal and 5 or False for normal text.

    You can provide an array of characters to use, a single character to use or a string which 
    the function will split into an array and use (after remove any duplicates).

    Examples:

        Default:  64 character string using standard and special characters and outputting in text.

            Input: randomToken();
            Output: #Z=9%|b.S$1\R}cj)rblGAQn_,g=.gM~K{@u=aY&Z1d7HOlP2)kLZIV%{h2gj61[

        32 character token using standard and special characters and output text.

            Input:   randomToken(16);
            Output:  Ps%X5&:f,9S|F:`8\zSW%(Wldz#siz44

        16 character token using standard and special characters and in output base-2 The output length 
        selected was 16 characters but due to the output being converted to Binary it will actually
        be 128 characters (16 * 8).

            Input:   randomToken(16, 1);
            Output:  00111100001110000011101000111101100110001000111011001101111001101111001110110001010001001001111001001100001011100011100100010110100111001

        16 character token using standard and special characters and output in base-8 The output length 
        selected was 16 characters but due to the output being converted to Octal it will actually
        be 48 characters (16 * 3).

            Input:   randomToken(16, 2);
            Output:  142074146170166155067050061101173076156162051167

        16 character token using standard and special characters and output in base-10 The output length 
        selected was 16 characters but due to the output being converted to Decimal it will actually
        be 32 to 48 characters (16 * 2|3).

            Input:   randomToken(16, 3);
            Output:  834698110507238106124121361177411210470

        16 character token using standard and special characters and output in base-16 The output 
        length selected was 16 characters but due to the output being converted to Hexadecimal it 
        will actually be 64 characters (16 * 4).

            Input:   randomToken(16, 4);
            Output:  0x5c0x4e0x7a0x380x320x500x640x520x5f0x4f0x760x4d0x440x4a0x630x6d

        16 character token using standard and special characters and output in text.

            Input:   randomToken(16, 5); OR randomToken(16, false);
            Output:  d2C^.88~7S[!LNHH

        32 character token using only special characters and output in text.

            Input:   randomToken(16, false, false);
            Output:  +}*|%?"/=`)(~#*`^.+:"[^~^'\,({~'

        32 character token using only standard characters and output in text.

            Input:   randomToken(16, false, true, false);
            Output:  BAgL1HnYuykKJiMQKH7LBC4Xjr2j22QH

        128 character token using only the characters #, $, and @.

            Input:   randomToken(128, false, false, false, '#$@')); OR randomToken(128, false, false, false, array('#', '$', '@'));
            Output:  @@#$$@#@$#$@#@@##$#$#@###$@#$@$@$@#$$@##@#$@####@@$@$##$#@$##@$#@$#$$@#$$#@#@##$##@@$$@@$##$#@$@@#$@$@@@$#@$@#$@@@@@@@######$##@ 
    function randomToken($len = 64, $output = 5, $standardChars = true, $specialChars = true, $chars = array()) {
        $out = '';
        $len = intval($len);
        $outputMap = array(1 => 2, 2 => 8, 3 => 10, 4=> 16, 5 => 10);
        if (!is_array($chars)) { $chars = array_unique(str_split($chars)); }
        if ($standardChars) { $chars = array_merge($chars, range(48, 57),range(65, 90), range(97, 122)); }
        if ($specialChars) { $chars = array_merge($chars, range(33, 47),range(58, 64), range(91, 96), range(123, 126)); }
        array_walk($chars, function(&$val) { if (!is_int($val)) { $val = ord($val); } });
        if (is_int($len)) {
            while ($len) {
                $tmp = ord(openssl_random_pseudo_bytes(1));
                if (in_array($tmp, $chars)) {
                    if (!$output || !in_array($output, range(1,5)) || $output == 3 || $output == 5) { $out .= ($output == 3) ? $tmp : chr($tmp);  }
                    else { 
                        $based = base_convert($tmp, 10, $outputMap[$output]);
                        $out .= ((($output == 1) ? '00' : (($output == 4) ? '0x' : '')) . (($output == 2) ? sprintf('%03d', $based) : $based)); 
                    }
                    $len--;
                }
            }
        }
        return (empty($out)) ? false : $out;
    }

Comments

Sign in to comment.
Typo   -  Mar 08, 2014

I have made some serious enhancements so if you looked at this before reading this post, look again as if its new.

 Respond  
Typo   -  Mar 06, 2014

I had formatted the description with indenting on the examples but all the leading spaces were stripped when I posted it here. Sorry if it turns out to be a bit difficult to read.

EDIT* I will be updating this function tonight with additional functionality.

Hawkee  -  Mar 06, 2014

I plan to implement a markdown parser for these descriptions to add more flexibility.

Typo  -  Mar 07, 2014

Awesome!

Hawkee  -  Mar 22, 2014

Almost done with markdown support.

Hawkee  -  Nov 06, 2014

I finally finished Markdown support a few weeks ago. Sorry it took so long!

Sign in to comment

Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.