# Don't use base_convert on random tokens

The PHP function `base_convert`

can convert numbers to a different numeric system. This can be used for example to convert a number to a sequence of letters and numbers. However, because it has limited precision it is not suitable for random tokens such as those used for session tokens or CSRF tokens.

Consider the following code from FOSOAuthServerBundle:

```
class Random
{
public static function generateToken()
{
$bytes = false;
if (function_exists('openssl_random_pseudo_bytes') && 0 !== stripos(PHP_OS, 'win')) {
$bytes = openssl_random_pseudo_bytes(32, $strong);
if (true !== $strong) {
$bytes = false;
}
}
// let's just hope we got a good seed
if (false === $bytes) {
$bytes = hash('sha256', uniqid(mt_rand(), true), true);
}
return base_convert(bin2hex($bytes), 16, 36);
}
}
```

The variable `$bytes`

will contain some more or less random data. This is binary data, which we want to fall in the ASCII range so that we can use it in cookies and query strings. The code uses the combination of `bin2hex`

and `base_convert`

for this. The function `bin2hex`

convert the binary to hexadecimal, and the function `base_convert`

convert it to base 36. Base 36 consists of letters and numbers, so this should give us a compact token.

Unfortunately, `base_convert`

does not perform its job correctly. Note what happens when we convert a hash to base 36 and back using `base_convert`

:

```
echo base_convert("adc83b19e793491b1c6ea0fd8b46cd9f32e592fc", 16, 36);
// kaseilp6gls8scsgcg08w48ow44wkos
echo base_convert("kaseilp6gls8scsgcg08w48ow44wkos", 36, 16);
// adc83b19e7934800000000000000000000000000
```

Converting back and forth replaced a large part of our hash with zeroes. This is because of how `base_convert`

works. It first converts the hexadecimal number to a 64-bits float number, and then convert that number to base 36. Because the float can contain just 64 bits, the resulting base 36 token contains at most 64 bits or 8 bytes of data.

The PHP manual warns against this:

Warning: base_convert() may lose precision on large numbers due to properties related to the internal “double” or “float” type used. Please see the Floating point numbers section in the manual for more specific information and limitations.

Don’t use `base_convert`

on your secure tokens.