Представлять хеш MD5 как целое число - PullRequest
15 голосов
/ 14 сентября 2009

В своей таблице базы данных пользователей в качестве идентификатора используется хеш MD5 адреса электронной почты пользователя.

Пример: email(example@example.org) = id(d41d8cd98f00b204e9800998ecf8427e)

К сожалению, теперь я должен представлять идентификаторы как целочисленные значения - чтобы иметь возможность использовать API, где идентификатор может быть только целым числом.

Теперь я ищу способ закодировать идентификатор в целое число для повторной отправки его при получении. Как я мог это сделать?

Мои идеи пока:

  1. convert_uuencode() и convert_uudecode() для хэша MD5
  2. заменить каждый символ хэша MD5 его ord() значением

Какой подход лучше? Знаете ли вы, еще лучшие способы сделать это?

Надеюсь, вы мне поможете. Заранее большое спасибо!

Ответы [ 8 ]

17 голосов
/ 14 сентября 2009

Будь осторожен. Преобразование MD5 в целое число потребует поддержки больших (128-битных) целых чисел. Скорее всего, используемый вами API будет поддерживать только 32-разрядные целые числа, или, что еще хуже, может иметь дело с числом с плавающей запятой. В любом случае, ваше удостоверение личности будет разграблено. Если это так, то просто произвольно назначить второй идентификатор - гораздо лучший способ справиться с ситуацией, чем пытаться преобразовать MD5 в целое число.

Однако, если вы уверены , что API может без проблем работать с произвольно большими целыми числами, вы можете просто преобразовать MD5 из шестнадцатеричного в целое число. PHP, скорее всего, не поддерживает эту встроенную функцию, так как он будет пытаться представить ее как 32-разрядное целое число или число с плавающей запятой; вам, вероятно, понадобится использовать PHP GMP library .

10 голосов
/ 14 сентября 2009

Есть веские причины, заявленные другими, для того, чтобы сделать это по-другому.

Но если вам нужно преобразовать хэш md5 в строку десятичных цифр (это то, что я думаю, вы действительно подразумеваете под "представлять целым числом", так как md5 уже является целым числом в строковой форме), и преобразовать его обратно в ту же строку md5:

function md5_hex_to_dec($hex_str)
{
    $arr = str_split($hex_str, 4);
    foreach ($arr as $grp) {
        $dec[] = str_pad(hexdec($grp), 5, '0', STR_PAD_LEFT);
    }
    return implode('', $dec);
}

function md5_dec_to_hex($dec_str)
{
    $arr = str_split($dec_str, 5);
    foreach ($arr as $grp) {
        $hex[] = str_pad(dechex($grp), 4, '0', STR_PAD_LEFT);
    }
    return implode('', $hex);
}

Демо-версия:

$md5 = md5('example@example.com');
echo $md5 . '<br />';  // 23463b99b62a72f26ed677cc556c44e8
$dec = md5_hex_to_dec($md5);
echo $dec . '<br />';  // 0903015257466342942628374306682186817640
$hex = md5_dec_to_hex($dec);
echo $hex;             // 23463b99b62a72f26ed677cc556c44e8

Конечно, вы должны быть осторожны при использовании любой строки, например, убедитесь, что используете их только в качестве типа строки, чтобы избежать потери начальных нулей, обеспечения правильной длины строк и т. Д.

7 голосов
/ 19 ноября 2013

Для 32-разрядной конденсации простое решение можно было бы сделать, выбрав 4 шестнадцатеричные пары (8 символов) хэша MD5, где каждая пара представляет один байт, и затем преобразовав это с intval().

Для 32-битного Int без знака:

$inthash = intval(substr(md5($str), 0, 8), 16);

Для положительного значения только 32-битного Int со знаком:

$inthash = intval(substr(md5($str), 0, 8), 16) >> 1;

Это, вероятно, будет работать только для значений до 64 бит (8 байт или 16 символов) для большинства современных систем, как указано в документации.

В системе, которая может вместить 64-битные Ints, стратегия разделения, которая использует весь 128-битный MD5-хэш, так как 2 Ints может выглядеть следующим образом:

$hash = md5($str);
$inthash1 = intval(substr($hash, 0, 16), 16);
$inthash2 = intval(substr($hash, 16, 16), 16);
1 голос
/ 03 января 2010

а как же:

$ float = hexdec (md5 ('string'));

или

$ int = (integer) (substr (hexdec (md5 ('string')), 0,9) * 100000000);

Определенно больше шансов на столкновение, но все же есть смысл использовать вместо хэша в БД?

ура

/ Marcin

1 голос
/ 14 сентября 2009

Почему ord ()? md5 выдает нормальное 16-байтовое значение, представленное вам в шестнадцатеричном формате для лучшей читаемости. Таким образом, вы не можете преобразовать 16-байтовое значение в 4 или 8-байтовое целое без потерь. Вы должны изменить некоторую часть своих алгоритмов, чтобы использовать это как идентификатор.

1 голос
/ 14 сентября 2009

Не могли бы вы просто добавить еще одно поле, которое было автоинкрементным int-полем?

1 голос
/ 14 сентября 2009

Вы можете использовать hexdec для анализа шестнадцатеричной строки и сохранения числа в базе данных.

0 голосов
/ 13 октября 2012

Используйте адрес электронной почты в качестве имени пустого временного файла в общей папке, например /var/myprocess/example@example.org

.

Затем вызовите ftok для имени файла. ftok вернет уникальный целочисленный идентификатор.

Это не будет гарантированно уникальным, но, вероятно, будет достаточно для вашего API.

...