Конвертировать MD5 в base62 для URL
У меня есть скрипт для преобразования в базу 62 (A-Za-z0-9), но как мне получить число из MD5?
Во многих местах я читал, что, поскольку число из MD5 больше, чем php может обрабатывать как целое число, оно будет неточным... Так как я все равно хочу короткий URL-адрес и не планирую использовать весь хэш, возможно, всего 8 символов об этом....
Итак, мой вопрос, как получить часть числа MD5-хеша?
Также плохая идея использовать только часть хеша MD5?
9 ответов
Я собираюсь предложить здесь кое-что другое. Поскольку вас интересует только использование десятичного фрагмента хеша md5, почему бы вам не использовать какой-либо другой короткий числовой хеш, такой как CRC32 или Adler? Вот пример:
$hash = sprintf('%u', crc32('your string here'));
Это создаст 8-значный хэш вашей строки.
РЕДАКТИРОВАТЬ: я думаю, что я неправильно понял вас, вот некоторые функции, которые обеспечивают преобразования в и из баз до 62.
РЕДАКТИРОВАТЬ (снова): для работы с числами произвольной длины вы должны использовать расширение bc_math или GMP, здесь есть функция, которая использует расширение bc_math и может также конвертировать из базы 2 в базу 62. Вы должны использовать это так:
echo bc_base_convert(md5('your url here'), 16, 62); // public base 62 hash
и обратное:
echo bc_base_convert('base 62 encoded value here', 62, 16); // private md5 hash
Надеюсь, поможет. знак равно
Если это возможно, я бы посоветовал не использовать хеш для ваших URL. В конце концов вы столкнетесь с коллизиями... особенно если вы усекаете хеш. Если вы решите внедрить систему, основанную на идентификаторах, в которой каждый элемент имеет уникальный идентификатор, головной боли будет гораздо меньше. Первый пункт будет 1
Второе будет 2
и т. д. --- если вы используете MySQL, просто добавьте столбец автоинкремента.
Чтобы сделать короткий идентификатор:
//the basic example
$sid = base_convert($id, 10, 36);
//if you're going to be needing 64 bit numbers converted
//on a 32 bit machine, use this instead
$sid = gmp_strval(gmp_init($id, 10), 36);
Чтобы сделать короткий идентификатор обратно в идентификатор base-10:
//the basic example
$id = base_convert($id, 36, 10);
//if you're going to be needing 64 bit numbers
//on a 32 bit machine, use this instead
$id = gmp_strval(gmp_init($shortid, 36));
Надеюсь это поможет!
Если вы действительно хотите базу 62 (что не может быть сделано с gmp
или же base_convert
), проверьте это: http://snipplr.com/view/22246/base62-encode--decode/
Вы можете сделать это следующим образом: (Не все шаги в php, я уже давно использовал его.)
Создайте хэш md5 для скрипта следующим образом:
$ hash = md5 (script, raw_output = true);
Преобразовать это число в базу 62.
Смотрите вопросы о базовом преобразовании чисел произвольного размера в PHP
Обрежьте строку до нужной вам длины.
Нет риска использовать только несколько битов md5. Все, что меняется, это опасность столкновений.
На самом деле есть реализация Java, которую вы, вероятно, могли бы извлечь. Это CMS-решение с открытым исходным кодом, которое называется Pulse.
Ищите здесь код toBase62()
а также fromBase62()
,
http://pulse.torweg.org/javadoc/src-html/org/torweg/pulse/util/StringUtils.java.html
Единственная зависимость в StringUtils
это класс LifeCycle, который предоставляет способ получить соленый хеш для строки, которую вы можете даже опустить все вместе или просто скопировать метод в вашу копию StringUtils
, Вуаля.
Вы можете попробовать base62x, чтобы получить безопасное и совместимое закодированное представление.
Вот для получения дополнительной информации о base62x, или просто -base62x
в -NatureDNS
,
shell> ./base62x -n 16 -enc 16AF
1Ql
shell> ./base62x -n 16 -dec 1Ql
16AF
shell> ./base62x
Usage: ./base62x [-v] [-n <2|8|10|16|32>] <-enc|dec> string
Version: 0.60
Начиная с PHP 5.3.2, GMP поддерживает базы до 62 (ранее было только 36), поэтому предложение Брианреависа было очень близко. Я думаю, что самый простой ответ на ваш вопрос таков:
function base62hash($source, $chars = 22) {
return substr(gmp_strval(gmp_init(md5($source), 16), 62), 0, $chars);
}
Преобразование из базы-16 в базу-62, очевидно, имеет космические преимущества. Обычный 128-битный MD5-хэш - это 32 символа в шестнадцатеричном формате, но в base-62 - только 22. Если вы храните хеши в базе данных, вы можете преобразовать их в необработанный двоичный файл и сэкономить еще больше места (16 байт для MD5).
Поскольку результирующий хеш является просто строковым представлением, вы можете просто использовать substr, если хотите только небольшую его часть (как это делает функция).
Вы можете сделать что-то вроде этого,
$hash = md5("The data to be hashed", true);
$ints = unpack("L*num", $hash);
$hash_str = base62($ints['num1']) . base62($ints['num2']) . base62($ints['num3']) . base62($ints['num4'])
Вот библиотека Java с открытым исходным кодом, которая преобразует строки MD5 в строки Base62 https://github.com/inder123/base62
Md5ToBase62.toBase62("9e107d9d372bb6826bd81d3542a419d6") ==> cbIKGiMVkLFTeenAa5kgO4
Md5ToBase62.fromBase62("4KfZYA1udiGCjCEFC0l") ==> 0000bdd3bb56865852a632deadbc62fc
Преобразование является двусторонним, поэтому вы вернете исходный md5, если преобразуете его обратно в md5:
Md5ToBase62.fromBase62(Md5ToBase62.toBase62("9e107d9d372bb6826bd81d3542a419d6")) ==> 9e107d9d372bb6826bd81d3542a419d6
Md5ToBase62.toBase62(Md5ToBase62.fromBase62("cbIKGiMVkLFTeenAa5kgO4")) . ==> cbIKGiMVkLFTeenAa5kgO4
`` `
Вы можете использовать слегка модифицированную Base 64 с -
а также _
вместо +
а также /
:
function base64_url_encode($str) {
return strtr(base64_encode($str), array('+'=>'-', '/'=>'_'));
}
function base64_url_decode($str) {
return base64_decode(strtr($str, array('-'=>'+', '_'=>'/')));
}
Кроме того, вы можете удалить конечную прокладку =
персонажи.
И чтобы получить необработанное значение MD5 (двоичная строка), установите второй параметр (с именем $raw_output
в руководстве) к истине:
$raw_md5 = md5($str, true);