Hello,
base_convert converts between numerical bases, such as from decimal to hex. It stores an intermediate result in a double, and thus loses precision for big numbers. This is a problem when used on big numbers in security contexts. This semi-often happens when users want to create a "nice" random token:
$token = base_convert(bin2hex(random_bytes(16)), 16, 36));
// "7nr0r976rl8o4wkwkkkcc84og"
This looks like a nice random string, but converting it back to hex shows that it is actually mostly zero:
var_dump(base_convert("7nr0r976rl8o4wkwkkkcc84og", 36, 16));
// "8161d6d5f47bb0000000000000000000"
Should base_convert raise a notice or warning when it cannot convert a number precisely? On one hand, silent conversion to floating point is just fact of life for PHP. But I would argue that in this case it is unexpected because both the input and output are strings. The loss of precision is documented in the manual, but it is not obvious from the result, and it has clear security impact. What do you think?
Regards,
Sjoerd Langkemper
Hello,
Should base_convert raise a notice or warning when it cannot convert a
number precisely? On one hand, silent conversion to floating point is
just fact of life for PHP. But I would argue that in this case it is
unexpected because both the input and output are strings. The loss of
precision is documented in the manual, but it is not obvious from the
result, and it has clear security impact. What do you think?
Alternatively, could the base conversion be made via bcmath to retain
all the digits instead? Then not only will the "nicely random" string
remain nicely random, but the warning in the manual could be removed as
well.
Alternatively, could the base conversion be made via bcmath to retain
all the digits instead?
I agree this would make base_convert more useful, and it is technically possible to make base_convert work with arbitrary large numbers, but this is hard to do in a backwards compatible way. Users who currently create their session tokens or encryption keys using base_convert rely on the loss of precision, and their application will break when base_convert is suddenly improved to have arbitrary precision.
I guess it is possible to add a $precision=false parameter. That wouldn't win a beauty contest, but it would make the new behavior opt-in and thus backwards compatible.
Regards,
Sjoerd
Hi
Am 2026-06-18 11:59, schrieb Sjoerd Langkemper:
This is a problem when used on big numbers in security contexts. This
semi-often happens when users want to create a "nice" random token:
Is this actually a thing that happens in security contexts? I'm only
ever seeing base64_encode() being applies to random_bytes()
directly.
But as to the question itself: I consider a warning to be appropriate
when the function does not what you expect it to do and I think adding
it would be in line with the “input validation” policy:
https://wiki.php.net/rfc/policy-exempt-type-value-error-bc-policy.
Best regards
Tim Düsterhus