0

I'm trying to generate an access token in php for user authorization

I used the following:

base64_encode(com_create_guid());

is this correct use in this context? and what is meant by "cryptographically secure"?

EDIT:

First, I was going to generate a random string using a function like this,

function generateRandomString($length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
}

but then I read about the token has to be cryptographically secure, and I can't really get what is this exactly or precisely.

then I went to com_create_guid() , but I noticed that com_create_guid() generates UUID, which does not include all characters (just numbers + a-f of hex). So I thought that base64 encoding may be suitable to convert this into a full character token (not for security).

here I'm asking about this being suitable for generating an access token, and if not is there a better way for generating it?

Community
  • 1
  • 1
Saif
  • 502
  • 5
  • 15
  • Base64 is completely unsafe and easily decoded. It should not be used ever as a token within a URL. It is only reasonable to use base64 within a header only when using SSL – pczeus Feb 05 '17 at 02:46
  • @pczeus from [this answer](http://stackoverflow.com/a/3557678/6778019) : UUIDs are also sometimes stored as a base64 or ascii85 encoded string to save space for transmission over transports that are not binary-safe, and adherence to the RFC is not required. so this is not for security it's just for formatting – Saif Feb 05 '17 at 16:19

2 Answers2

1

Returns a random string with crypto-strength given in $len. The string is always longer than $len by 3-4 expansion (that is, it takes 4 characters to encode 3 length). Pass a $len of at least 16 for good strength.

Stolen from https://stackoverflow.com/a/8429944/14768 and edited to use /dev/random instead of /dev/urandom

function generateRandomString($len)
{
    $fp = @fopen('/dev/random','rb');
    $result = '';
    if ($fp !== FALSE) {
        $result .= @fread($fp, $len);
        @fclose($fp);
    }
    else
    {
        trigger_error('Can not open /dev/urandom.');
    }
    // convert from binary to string
    $result = base64_encode($result);
    // remove none url chars
    $result = strtr($result, '+/', '-_');
    // Remove = from the end
    $result = str_replace('=', ' ', $result);
    return $result;
}

When wanting crypt-strength stuff use crypt-strength stuff. guidv4 is not guaranteed to be crypt-strength.

Community
  • 1
  • 1
Joshua
  • 40,822
  • 8
  • 72
  • 132
  • I develop on **Windows** 10 and of course there no `'/dev/random'` I searched and found this [wikipedia link](https://en.wikipedia.org/wiki/Entropy_(computing)#Windows) which states that Microsoft Windows uses **CryptoAPI** to gather entropy in a similar fashion to Linux kernel's /dev/random, and that CAPI can get entropy by calling CAPI's CryptGenRandom(). I searched for this in **php**, I found [random_int](http://php.net/manual/en/function.random-int.php). The docs says that on Windows, » CryptGenRandom() will always be used. But random_int takes min and max, can we use it in this context? – Saif Feb 06 '17 at 02:50
  • @Saif: Nope. You should now add tag Windows to your question. The answer is now likely to be OS specific. :( – Joshua Feb 06 '17 at 04:00
  • thank Joushua, eventually, I'll deploy on ubuntu or centos, and most probably I'll use this, but I wanted to test it locally in my development environment. I might install ubuntu on windows Hyper-V to test this function, thank you, and any suggestion to test this function on windows will be appreciated :) – Saif Feb 06 '17 at 09:52
  • @Saif: You are now outside my experience. – Joshua Feb 06 '17 at 16:11
0

You might want to use this:

function guidv4()
{
    if (function_exists('com_create_guid') === true)
        return trim(com_create_guid(), '{}');

    $data = openssl_random_pseudo_bytes(16);
    $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
    $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
    return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}

source: http://php.net/manual/en/function.com-create-guid.php#117893

This code is more cryptographically secure, however, for what you are doing you should be fine.

Cryptographically secure in layman's terms is something that is random, and is hard to recreate or predict.

  • thank you for reply, but one point: does "`base64`- ing" has effect on security? – Saif Feb 05 '17 at 01:00
  • No. Don't use even guidv4(); it is probably reading from /dev/urandom for seed. Always use /dev/random for seed in crypto cases. – Joshua Feb 05 '17 at 21:25