, base_convert(), . , , . , . , 256 ( ) base85 .
GMP
You can use GMP to accomplish this by converting bin ↔ hex two times unnecessarily, and is also limited by the base62.
<?php
$data = openssl_random_pseudo_bytes(256);
$base62 = gmp_strval( gmp_init( bin2hex($data), 16), 62 );
$decoded = hex2bin( gmp_strval( gmp_init($base62, 62), 16 ));
var_dump( strcmp($decoded, $data) === 0 );
Pure php
If you want to move beyond base62 to base85 or a slight performance improvement, you'll need something like the following.
<?php
function divmod(&$binary, $base, $divisor, $start = 0)
{
$size = strlen($binary);
$remainder = 0;
for ($i = $start; $i < $size; $i++) {
$digit = ord($binary[$i]);
$temp = ($remainder * $base) + $digit;
$binary[$i] = chr($temp / $divisor);
$remainder = $temp % $divisor;
}
return $remainder;
}
function encodeBase62($binary)
{
$charMap = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$base = strlen($charMap);
$size = strlen($binary);
$start = $size - strlen(ltrim($binary, "\0"));
$encoded = "";
for ($i = $start; $i < $size; ) {
$idx = divmod($binary, 256, $base, $i);
$encoded = $charMap[$idx] . $encoded;
if (ord($binary[$i]) == 0) {
$i++;
}
}
$encoded = str_pad($encoded, $start, "0", STR_PAD_LEFT);
return $encoded;
}
function decodeBase62($ascii)
{
$charMap = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$base = strlen($charMap);
$size = strlen($ascii);
$start = $size - strlen(ltrim($ascii, "0"));
$binary = "";
for ($i = $start; $i < $size; $i++) {
$byte = strpos($charMap, $ascii[$i]);
if ($byte === false) {
throw new OutOfBoundsException("Invlaid encoding at offset '{$ascii[$i]}'");
}
$binary .= chr($byte);
}
$decode = "";
for ($i = 0; $i < $size; ) {
$idx = divmod($binary, $base, 256, $i);
$decode = chr($idx) . $decode;
if (ord($binary[$i]) == 0) {
$i++;
}
}
$decode = ltrim($decode, "\0");
$decode = str_pad($decode, $start, "\0", STR_PAD_LEFT);
return $decode;
}
$data = openssl_random_pseudo_bytes(256);
$base62 = encodeBase62($data);
$decoded = decodeBase62($base62);
var_dump( strcmp($decoded, $data) === 0 );