Конвертировать 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. Все, что меняется, это опасность столкновений.

На самом деле есть реализация 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);
Другие вопросы по тегам