Представлять хеш MD5 как целое число
Какой подход лучше? Знаете ли вы еще лучшие способы сделать это?
Надеюсь, ты поможешь мне. Большое вам спасибо заранее!
У вас нет других, возможно, стажеров, ценностей для идентификации ваших пользователей? Ну, у вас должен быть хотя бы PK для вашей пользовательской таблицы.
Использование хеша MD5 в качестве первичного ключа вашей пользовательской таблицы, как правило, не очень хорошая идея. Автоматическое увеличение / последовательный идентификатор целого числа составляет 4-8 байтов. Хэш md5 составляет 32 байта. Сравнение целочисленных значений (например, каждый раз, когда вы ПРИСОЕДИНЯЕТЕСЬ к этой таблице или ВЫБИРАЕТЕ строку из нее) будет во много раз быстрее, чем сравнение 32-байтовых строк, а целочисленные значения потребуют меньше памяти. И действительно . если вы хотите использовать строковое значение, почему бы не использовать сам адрес электронной почты? В большинстве случаев это будет 32 байта или меньше.
@Frank Farmer: Да, в большинстве случаев было бы лучше взять целое число в качестве первичного ключа. Но мои пользователи не должны иметь возможность перечислять идентификаторы. Они могут легко изменить параметры GET и пройти все идентификаторы. Это не должно быть возможно, поэтому я беру хэши.
Это, безусловно, вызывает озабоченность, но есть более эффективные способы решения этой проблемы — нет необходимости разрабатывать схему базы данных вокруг нее. Только не выставляйте идентификаторы как параметры GET. И сделать проверку разрешений на уровне страницы. Если вы действительно женаты на идее хеширования, по крайней мере, используйте алгоритм хеширования, который отображается в 32/64 битное пространство int. В любом случае необработанный, несоленый хеш-адрес электронной почты MD5 не слишком безопасен для этих целей.
Вы никогда не должны получать идентификатор пользователя непосредственно от клиента и доверять ему. Вместо этого вы должны проверить, что клиент имеет действительные учетные данные и получить его идентификатор из базы данных. То, что вы делаете, это как ввод пароля в строке запроса.
8 ответов
Будьте осторожны. Преобразование MD5 в целое число потребует поддержки больших (128-битных) целых чисел. Скорее всего, API, который вы используете, будет поддерживать только 32-битные целые числа, или, что еще хуже, может иметь дело с числом в плавающей запятой. В любом случае, ваш идентификатор будет запутан. Если это так, просто назначить второй идентификатор произвольно — гораздо лучший способ справиться с вещами, чем пытаться преобразовать MD5 в целое число.
Однако, если вы уверены, что API может справиться с произвольно большими целыми числами без проблем, вы можете просто преобразовать MD5 из шестнадцатеричного в целое. Однако PHP, скорее всего, не поддерживает этот встроенный модуль, поскольку он попытается представить его как 32-битное целое число или плавающую точку; вам, вероятно, потребуется использовать PHP GMP library для этого.
+1 для намека на то, что результирующее значение может быть слишком большим для API даже при использовании пустых байтов в качестве целого числа. Вы должны найти другое решение для вашей проблемы «адрес электронной почты в целое число».
Большое спасибо! Будет ли это решение лучше, чем две мои идеи? $ id_integer = base_convert ($ id_string, 16, 10);
Прочтите предупреждение в документах base_convert ( php.net/manual/en/function.base-convert.php ) — оно НЕ подходит для больших чисел. И MD5 очень большие числа. Вы должны использовать библиотеку bigint, и API, к которому вы обращаетесь, тоже должен это делать — но я сомневаюсь, что это так. Просто добавьте еще один столбец и назначьте произвольные идентификаторы каждому пользователю, это будет намного проще.
Дайджест MD5 (хэш) составляет 128 бит (16 двоичных байтов, 32 шестнадцатеричных символа). Это может быть представлено двумя 8-байтовыми целыми числами. Используйте два больших целочисленных столбца в качестве первичного ключа. Если ваша программная среда не поддерживает внешние столбцы с несколькими столбцами, это может быть проблемой, в противном случае это будет простым решением.
Есть веские причины, заявленные другими, для того, чтобы сделать это по-другому.
Но если вы хотите сделать преобразование хеша 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('[email protected]'); echo $md5 . '
'; // 23463b99b62a72f26ed677cc556c44e8 $dec = md5_hex_to_dec($md5); echo $dec . '
'; // 0903015257466342942628374306682186817640 $hex = md5_dec_to_hex($dec); echo $hex; // 23463b99b62a72f26ed677cc556c44e8
Конечно, вам нужно быть осторожным, используя любую строку, например, чтобы использовать их только как строковый тип, чтобы не потерять ведущие нули, гарантируя, что строки имеют правильную длину и т.д.
Большое спасибо. Вот как это будет работать. Но теперь я вижу, что все остальные хотели сказать: новое целое число очень длинное. И ведущий ноль — тоже проблема.
Рад помочь. Помните, что строка десятичных цифр и строка шестнадцатеричных цифр (строка md5) математически не равны; они являются просто «переводами» друг друга, созданными этими сопутствующими функциями, в их соответствующие наборы цифровых символов.
Для 32-разрядной конденсации можно было бы сделать простое решение, выбрав четыре гексагона (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);
Представить хеш MD5 как целое число
В моей таблице базы данных пользователей я принимаю хеш MD5 адреса электронной почты пользователя в качестве идентификатора.
Пример: email(example@example.org) = id(d41d8cd98f00b204e9800998ecf8427e)
К сожалению, теперь я должен представлять идентификаторы как целочисленные значения, чтобы иметь возможность использовать API, где id может быть только целым числом.
Теперь я ищу способ кодирования 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 . '
'; // 23463b99b62a72f26ed677cc556c44e8 $dec = md5_hex_to_dec($md5); echo $dec . '
'; // 0903015257466342942628374306682186817640 $hex = md5_dec_to_hex($dec); echo $hex; // 23463b99b62a72f26ed677cc556c44e8
Конечно, вам нужно быть осторожным, используя любую строку, например, чтобы использовать их только как строковый тип, чтобы не потерять ведущие нули, гарантируя, что строки имеют правильную длину и т. Д.
Для 32-битной конденсации можно было бы сделать простое решение, выбрав четыре гексагона (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 для разбора шестнадцатеричной строки и сохранения номера в базе данных.
Не могли бы вы просто добавить другое поле, которое было полем auto-increment int?
Почему ord ()? md5 производит нормальное 16-байтовое значение, представленное вам в шестнадцатеричном формате для лучшей читаемости. Таким образом, вы не можете преобразовать 16-байтовое значение в 4 или 8 байтовое целое без потерь. Вы должны изменить часть своих алгоритмов, чтобы использовать это как id.
$ int = (integer) (substr (hexdec (md5 (‘string’)), 0,9) * 100000000);
Определенно большие шансы на столкновение, но все же хороший enaugh для использования вместо хэша в DB, хотя?
Используйте адрес электронной почты в качестве имени пустого временного файла в общей папке, например /var/myprocess/example@example.org.
Затем вызовите ftok на имя файла. ftok вернет уникальный идентификатор целого числа.
Не гарантируется, что он будет уникальным, но, вероятно, этого будет достаточно для вашего API.