Похоже, ваши цели: 1. до визуально скрыть URL , и 2. чтобы вообще кодировать данные компактно для использования в URL .
Во-первых, нам нужно скрыть URL. Поскольку URL-адреса используют большую часть словаря Base64, любая кодировка, создающая двоичный файл (который затем должен быть Base64-ed), вероятно, просто увеличит размер. Лучше всего держать словарь в безопасном для URL диапазоне с минимальной необходимостью экранирования при применении urlencode()
. То есть Вы хотите это:
/**
* Rot35 for URLs. To avoid increasing size during urlencode(), commonly encoded
* chars are mapped to more rarely used chars (end of the uppercase alpha).
*
* @param string $url
* @return string
*/
function rotUrl($url) {
return strtr($url,
'abcdefghijklmnopqrstuvwxyz0-:/?=&%#123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0-:/?=&%#');
}
Теперь, для сохранения байтов, мы можем закодировать схему URL в один символ (скажем, h
для HTTP, H
для HTTPS) и преобразовать измерения в основание 32. Подводя итог:
function obscure($width, $height, $url) {
$dimensions = base_convert($width, 10, 32) . "."
. base_convert($height, 10, 32) . ".";
preg_match('@^(https?)://(.+)@', $url, $m);
return $dimensions . (($m[1] === 'http') ? 'h' : 'H') . rotUrl($m[2]);
}
function unobscure($str) { /* exercise for the reader! */ }
$url = 'https://en.wikipedia.org/w/index.php?title=Special%3ASearch&search=Base64';
$obs = obscure(550, 300, $url);
// h6.9c.H5E.N9B9G5491.FI7UNU9E45O.G8GVK9KC5W-G5391CYcj-51I38XJ51I38Wk1J5fd
Поскольку мы избегали использования символов, не безопасных для URL, если они помещаются в строку запроса (с urlencode
), она не сильно возрастает (в данном случае вовсе).
Кроме того, вы можете захотеть подписать эту строку, чтобы люди, которые знают кодировку, все еще не могли указать свои собственные параметры через URL. Для этого вы должны использовать HMAC и Base64URL-кодировать хэш. Вы также можете просто сохранить подстроку хеша (~ 6 бит на символ) для экономии места. sign()
(ниже) добавляет 8-символьный MAC-адрес (48 бит хеш-функции при 6 битах / символ):
function sign($key, $data) {
return $data . _hmac($key, $data, 8);
}
function verify($key, $signed) {
$mac = substr($signed, -8);
$data = substr($signed, 0, -8);
return $mac === _hmac($key, $data, 8) ? $data : false;
}
function _hmac($key, $data, $macLength) {
$mac = substr(base64_encode(hash_hmac('sha256', $data, $key, true)), 0, $macLength);
return strtr($mac, '+/', '-_'); // for URL
}
$key = "Hello World!";
$signed = sign($key, $obs); // appends MAC: "w-jjw2Wm"
$obs = verify($key, $signed); // strips MAC and returns valid data, or FALSE
Обновление: улучшена Функция RotURL .