Подтвердить что ты не робот

Уникальное генерирование ключей

Я ищу способ, в частности, в PHP, который гарантированно будет всегда иметь уникальный ключ.

Я сделал следующее:

strtolower(substr(crypt(time()), 0, 7));

Но я обнаружил, что время от времени я получаю дубликат ключа (редко, но часто достаточно).

Я также думал о том, чтобы делать:

strtolower(substr(crypt(uniqid(rand(), true)), 0, 7));

Но, согласно сайту PHP, uniqid() может, если uniqid() вызывается дважды в одну и ту же микросекунду, он может генерировать тот же ключ. Я думаю, что добавление rand() было бы редко, но все же возможно.

После строк, упомянутых выше, я также удаляю символы, такие как L и O, поэтому он менее запутан для пользователя. Возможно, это часть причины дубликатов, но все же необходимо.

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

Любые другие мысли? Есть ли там какие-то веб-сайты, которые уже делают это, которые имеют какой-то API или просто возвращают ключ. Я нашел http://userident.com, но я не уверен, что ключи будут полностью уникальными.

Это нужно запускать в фоновом режиме без ввода пользователем.

4b9b3361

Ответ 1

Есть только 3 способа генерации уникальных значений, скорее это пароли, идентификаторы пользователей и т.д.:

  • Используйте эффективный GUID-генератор - они длинные и не могут быть сжаты. Если вы используете только часть , вы НЕИСПРАВНОСТЬ.
  • По крайней мере часть номера последовательно генерируется из одной последовательности. Вы можете добавить пух или кодирование, чтобы сделать его менее последовательным. Преимущество заключается в том, что они начинаются с недостатка - им нужен один источник. Работа для ограничения единственного источника состоит в том, чтобы иметь нумерованные источники, поэтому вы включаете [источник #] + [seq #], а затем каждый источник может генерировать свою собственную последовательность.
  • Сгенерировать их с помощью других средств, а затем проверить их на одну историю ранее созданных значений.

Любой другой метод не гарантируется. Имейте в виду, в основном вы генерируете двоичное число (это компьютер), но тогда вы можете закодировать его в шестнадцатеричном, десятичном, базовом 64 или списке слов. Выберите кодировку, которая соответствует вашему использованию. Обычно для введенных пользователем данных вы хотите изменить Base32 (на что вы намекали).

Заметка о GUIDS: они набирают силу уникальности по своей длине и методу их генерации. Все, что меньше 128 бит, небезопасно. Помимо генерации случайных чисел есть характеристики, которые входят в GUID, чтобы сделать его более уникальным. Имейте в виду, что они практически уникальны, но не полностью уникальны. Возможно, хотя практически невозможно дублировать.

Обновлено примечание о GUIDS. После написания этого я узнал, что многие генераторы GUID используют криптографически безопасный генератор случайных чисел (трудно или невозможно предсказать следующее генерируемое число и вряд ли повторится). На самом деле существует 5 различных алгоритмов UUID. Алгоритм 4 - это то, что Microsoft в настоящее время использует для API GUID поколения Windows. A GUID - это реализация Microsoft стандарта UUID.

Обновить. Если вам нужно от 7 до 16 символов, вам нужно использовать либо метод 2, либо 3.

Нижняя строка: Честно говоря, нет такой вещи, как совершенно уникальная. Даже если вы поехали с последовательным генератором, у вас в конечном итоге закончится хранение, используя все атомы во Вселенной, таким образом, зацикляясь на себе и повторяя. Ваша единственная надежда - это тепловая смерть Вселенной до достижения этой точки.

Даже лучший генератор случайных чисел имеет возможность повторять равный общему размеру случайного числа, которое вы генерируете. Возьмите четверть, например. Это полностью случайный генератор бит, и его шансы повторения равны 1 в 2.

Итак, все сводится к вашему порогу уникальности. Вы можете иметь 100% уникальность в 8 цифрах для 1099 511 627 776 номеров, используя последовательность, а затем base32, кодирующую ее. Любой другой метод, который не включает проверку против списка прошлых чисел, имеет только шансы, равные n/1099,511,627,776 (где n = число предыдущих чисел) не уникальное.

Ответ 2

Любой алгоритм приведет к дублированию.

Поэтому могу ли я предложить вам использовать существующий алгоритм * и просто проверить наличие дубликатов?

* Незначительное дополнение: если uniqid() может быть не уникальным в зависимости от времени, также включать глобальный счетчик, который вы увеличиваете после каждого вызова. Таким образом, что-то другое даже в том же микросекунде.

Ответ 3

Без написания кода моя логика:

Создайте случайную строку из любых приемлемых символов, которые вам нравятся.
Затем добавьте половину даты (частичные секунды и все) в начало, а другую половину до конца (или где-нибудь посередине, если хотите).

Пребывайте JOLLY!
Н

Ответ 4

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

Ответ 5

Вам может быть интересна эта статья, которая касается одной и той же проблемы: GUID глобально уникальны, но подстроки GUID не являются.

Цель этого алгоритма - использовать комбинацию времени и местоположения ( "пространственно-временные координаты" для гиганта относительности) в качестве ключа уникальности. Тем не менее, хронометраж не является совершенным, поэтому существует вероятность того, что, например, два GUID генерируются в быстрой последовательности с одного и того же компьютера, настолько близкие друг к другу во времени, что временная метка будет одинаковой. То, в которое входит уникальный идентификатор.

Ответ 6

Обычно я делаю это так:

$this->password = '';

for($i=0; $i<10; $i++)
{
    if($i%2 == 0)
        $this->password .= chr(rand(65,90));
    if($i%3 == 0)
        $this->password .= chr(rand(97,122));
    if($i%4 == 0)
        $this->password .= chr(rand(48,57));
}

Я предполагаю, что есть некоторые теоретические дыры, но у меня никогда не было проблемы с дублированием. Я обычно использую его для временных паролей (например, после пароля reset), и он работает достаточно хорошо для этого.

Ответ 7

Вам может быть интересно, что Стив Гибсон сверх надежной реализации генератора паролей (нет источника, но у него есть подробное описание того, как он работает) на https://www.grc.com/passwords.htm.

Сайт создает огромные 64-символьные пароли, но, поскольку они полностью случайны, вы можете легко взять первые 8 (или сколько угодно) символов для менее безопасного, но "как можно более случайного" пароля.

EDIT: из ваших более поздних ответов я вижу, что вам нужно что-то большее, чем GUID, чем пароль, поэтому это, вероятно, не то, что вы хотите...

Ответ 8

Как заметил Фрэнк Крюгер, идите с генератором GUID.

Как этот

Ответ 9

Я все еще не понимаю, почему пароли должны быть уникальными? Какая минута, если у 2 ваших пользователей одинаковый пароль?

Предполагается, что мы говорим о паролях, привязанных к идентификаторам пользователей, а не только уникальным идентификаторам. Если это то, что вы ищете, почему бы не использовать GUID?

Ответ 10

Я действительно верю, что часть вашей проблемы заключается в том, что вы пытаетесь создать сингулярную функцию для двух разных применений... пароли и транзакционные_имя

это действительно две разные проблемные области, и на самом деле не лучше попытаться решить их вместе.

Ответ 11

Недавно мне нужен быстрый и простой случайный уникальный ключ, поэтому я сделал следующее:

$ukey = dechex(time()) . crypt( time() . md5(microtime() + mt_rand(0, 100000)) ); 

Итак, в основном, я получаю unix-время в секундах и добавляю случайную строку md5, созданную из времени + случайного числа. Это не самое лучшее, но для низкочастотных запросов это довольно хорошо. Это быстро и работает.

Я проверил, где я буду генерировать тысячи ключей, а затем искать повторы, и имея около 800 ключей в секунду, повторений не было, поэтому неплохо. Я думаю, это полностью зависит от mt_rand()

Я использую его для поискового трекера, где мы получаем скорость передачи около 1000 обследований в минуту... так что пока (пересекает пальцы) нет дубликатов. Конечно, скорость не постоянна (мы получаем материалы в определенное время дня), поэтому это не подлежит доказательству или наилучшему решению... наконечник использует инкрементное значение как часть ключа (в моем случае, Я использовал time(), но мог бы быть лучше).

Ответ 12

Включение части шифрования, которая не имеет большого отношения к созданию уникального значения, я обычно использую это:

function GetUniqueValue()
{
   static $counter = 0; //initalized only 1st time function is called
   return strtr(microtime(), array('.' => '', ' ' => '')) . $counter++;
}

При вызове в том же процессе счетчик $увеличивается, поэтому значение всегда уникально в том же процессе.

При вызове в разных процессах вам действительно не повезло, чтобы получить 2 вызова microtime() с одинаковыми значениями, считайте, что вызовы microtime() обычно имеют разные значения также при вызове в том же script.

Ответ 13

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