Представлять хэш MD5 в виде целого числа
Вопрос
В моей таблице базы данных пользователей я беру MD5-хэш адреса электронной почты пользователя в качестве идентификатора.
Пример: email(example@example.org) = id(d41d8cd98f00b204e9800998ecf8427e)
К сожалению, теперь мне приходится представлять идентификаторы в виде целых значений - чтобы иметь возможность использовать API, где id может быть только целым числом.
Теперь я ищу способ закодировать идентификатор в целое число для отправки и декодирования его снова при получении.Как я мог это сделать?
Мои идеи на данный момент:
convert_uuencode()
иconvert_uudecode()
для хэша MD5- замените каждый символ хэша MD5 на его
ord()
значение
Какой подход лучше?Знаете ли вы еще лучшие способы сделать это?
Я надеюсь, что вы сможете мне помочь.Заранее большое вам спасибо!
Решение
Будь осторожен. Преобразование MD5 в целое число потребует поддержки больших (128-битных) целых чисел. Скорее всего, используемый вами API будет поддерживать только 32-разрядные целые числа, или, что еще хуже, может иметь дело с числом с плавающей запятой. В любом случае, ваше удостоверение личности будет разграблено. Если это так, то просто произвольно назначить второй идентификатор - лучший способ справиться с ситуацией, чем пытаться преобразовать MD5 в целое число.
Однако, если вы уверены , что API может работать с произвольно большими целыми числами без проблем, вы можете просто преобразовать MD5 из шестнадцатеричного в целое число. PHP, скорее всего, не поддерживает эту встроенную функцию, так как он будет пытаться представить ее как 32-разрядное целое число или число с плавающей запятой; вам, вероятно, потребуется использовать библиотеку PHP GMP . р>
Другие советы
Есть веские причины, изложенные другими, для того, чтобы сделать это по-другому.
Но если то, что вы хотите сделать, это преобразовать хэш 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
Конечно, вам нужно было бы быть осторожным, используя любую строку, например, использовать их только как строковый тип, чтобы избежать потери начальных нулей, убедиться, что строки имеют правильную длину, и т.д.
Для 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);
Вы можете использовать hexdec для анализа шестнадцатеричной строки и сохранения номер в базе данных.
Не могли бы вы просто добавить еще одно поле, которое было автоинкрементным int-полем?
Почему ord ()? md5 выдает нормальное 16-байтовое значение, представленное вам в шестнадцатеричном формате для лучшей читаемости. Таким образом, вы не можете преобразовать 16-байтовое значение в 4 или 8-байтовое целое без потерь. Вы должны изменить некоторую часть своих алгоритмов, чтобы использовать это в качестве идентификатора.
о чем:
$float = шестнадцатеричный код (md5('строка'));
или
$int = (целое число) (substr(hexdec(md5('строка')),0,9)*100000000);
Определенно больше шансов на столкновение, но все же достаточно хорошо использовать вместо хэша в БД, хотя?
ваше здоровье,
/Марчин
Используйте адрес электронной почты в качестве имени пустого временного файла в общей папке, например /var/myprocess/example@example.org
Затем вызовите ftok для имени файла. ftok вернет уникальный целочисленный идентификатор.
Это не будет гарантированно уникальным, но, вероятно, будет достаточно для вашего API.