The response of @Valdeir Psr answers the question and solves the problem. However, I had a completely different idea of solving the situation by using bitwise.
I thought of simply dividing the value every 6 bits, then encoding it for Base64. This would not be approve of side-Channel attacks (in the same way as the original PHP), but would be sufficient for the purpose, I believe.
I tried to execute this idea, and... it worked. So, I’m sharing here, although I will use the pack
.
So just do:
function base64_encode_int64(int $int) : string {
$alfabeto = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
$base64 = '';
for($l = 58; $l > 0; $l -= 6){
$base64 .= $alfabeto[($int >> $l) & 0x3F];
}
$base64 .= $alfabeto[($int << 2) & 0x3F];
return $base64;
}
The last shift must be inverted, because it has only 4 bits, 6 bits are needed. Then it is necessary to add 2 bits at the end, for this reason the offset "to the opposite side".
To decode we use the |
, which is the simplest solution, I believe.
function base64_decode_int64(string $base64) {
$alfabeto = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
$int = 0;
if(mb_strlen($base64, '8bit') !== 11){
return false;
}
for($l = 58; $l > -3; $l -= 6){
$letra = strpos($alfabeto, $base64[(58-$l)/6]);
if($letra === false) {
return false;
}
if($l > 0){
$int |= ($letra) << $l;
}else{
$int |= ($letra) >> 2;
}
}
return $int;
}
I don’t believe that the strpos
is the best option, plus the amount of if
is in bothering a little. That was necessary because the input ($base64
) must use the same dictionary, so must return false
in case of error and limited to 11 characters.
The if($l > 0){
I brought it into the for
, but I don’t believe it’s not ideal. I did it so I wouldn’t have to create a new condition outside the loop (duplicate the if($letra)
), but I believe there must be a way to make this "universal", maybe doing some shifts before (the other way around), I don’t know.
Now the tests:
echo $int = 5460109885665973483;
echo PHP_EOL;
echo $b64 = base64_encode_int64($int);
echo PHP_EOL;
echo base64_decode_int64($b64);
Returns:
5460109885665973483
S8Y1Axm4FOs
5460109885665973483
Test it out here
The
pack
always saving. For the first time I saw usefulness in the other options of the pack, besides theC
and ofH
, I’ll investigate them further. D– Inkeliz