Уникальный, непредсказуемый, 12-значный, целочисленный идентификатор

Как бы я начал генерировать это … Я хочу сохранить свой первичный ключ последовательным и иметь 12-значный уникальный контакт, сгенерированный для каждого нового объекта, добавленного в базу данных.

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

Он должен быть целым числом, потому что у меня будут коды подтверждения, которые необходимо набирать на клавиатуре телефона.

Related of "Уникальный, непредсказуемый, 12-значный, целочисленный идентификатор"

Используйте конкатенацию уникального инкрементированного числа и произвольно сгенерированного числа.

Уникальное инкрементное число гарантирует, что результат уникален, а случайно созданное число делает его едва ли допустимым.

Это просто и гарантирует отсутствие столкновения (1). Результат является инкрементным , частично случайным и непредсказуемым (при условии, что часть случайного числа генерируется с хорошим PRNG).

(1): вам нужно либо набирать id либо random с нулями, либо отделять их каким-либо несимметричным символом.

С MySQL db это означает:

 CREATE TABLE foo ( id int not null auto_increment, random int not null, ... primary key (id) ); 

Возможно, вы можете использовать UUID_SHORT() . Не более 12 цифр, но все же может быть жизнеспособным вариантом:

 mysql> select uuid_short(); +-------------------+ | uuid_short() | +-------------------+ | 22048742962102272 | +-------------------+ 

Так:

 INSERT INTO `table` (`id`, `text`) VALUES (UUID_SHORT(), 'hello world!'); 

Примечание. Если вы действительно хотите иметь ровно 12 цифр, тогда даже не пытайтесь подстроить результат, если бы не гарантировали уникальность идентификатора и могли вызвать конфликты.

 <?php $allowed_characters = array(1,2,3,4,5,6,7,8,9,0); for($i = 1;$i <= 12; $i++){ $pass .= $allowed_characters[rand(0, count($allowed_characters) - 1)]; } echo $pass; ?> 

demo: http://sandbox.phpcode.eu/g/c0190/4

Один из методов заключается в том, чтобы взять ваше первичное значение ключа, солить его несколькими другими случайными битами данных (имя пользователя, текущее время, идентификатор процесса, фиксированную строку и т. Д.) И хешировать его с помощью md5 или sha1. Затем вы берете хэш-строку и преобразуете ее в цифры посредством основных операций с строкой. Это даст вам относительно уникальный цифровой код.

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

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

Вы хотите две вещи

  1. уникальность
  2. дополнительный

Если вы хотите, чтобы и то и другое происходило из одной последовательности, вам не удастся (буквально). Уникальность гарантируется наличием большого пространства выборки + случайным + check-unique. Это означает, что фактическое число может находиться где угодно между выборкой.

Но если вы хотите уникальное свойство + incremental, вы делите пространство выборки на 2. В 64 попытках вы уменьшили бы пространство с пробелами в 64 бит до 1 бит пространства выборки.

Удачи !

Вообще, я предпочту сделать что-то немного более низкотехнологичное. Я скрываю значения в PHP и оставляю их как автоинкремент в JS.

 $seeds = array( /*series 100 of very large >= 10-digit numbers*/ ); $seedID = rand( count( $seeds ) ); // randomly choose one of those. // a string combination which represents the ID + some hash. $id = bcadd( $seeds[ $seedID ], /* id retrieved from database */ ); // make sure we've not accidentally passed the 10^12 point $id = bcmod( $id, 1000000000000 ); // make sure to pad $id = str_pad('' . $id, 3, "0", STR_PAD_LEFT); $outID = substr( $id, 0, 5 ) . $seedID . substr( $id, 6 ); 

Затем, при получении идентификатора от пользователя:

 $seedID = substr( $outID, 6, 2 ); $tmpID = substr( $outID, 0, 5 ) . substr( $outID, 8 ); $id = bcsub( $tmpID, $seeds[ $seedID ] ); // we passed the modulus se we need to add this back in. if( $id < 0 ) $id = bcmod( bcadd( $id, 1000000000000 ), 1000000000000 ); 

Это в основном означает, что вы просто затушевываете любое количество, которое вы хотите – вы можете использовать auto_increment с безнаказанностью!

Все решения до сих пор не имеют ничего общего с вашим приложением: безопасность !

Вы сказали, что будете использовать эти цифры в качестве (товарного) кода проверки – так что вы действительно хотите, чтобы это было непредсказуемо, иначе оно будет эксплуатироваться.

Ни встроенная функция RANDOM MySQL, ни какая-либо из случайных функций, предоставляемых PHP, сегодня являются безопасными случайными функциями. Они ведут себя псевдослучайно, хорошо, но все они предсказуемы!

Ваш единственный шанс – взломать что-то свое, используя /dev/urandom на машине * nix или используя Crypto API в Windows. OpenSSL действительно обеспечивает безопасные случайные числа на основе этих механизмов – вы можете повторно использовать это либо в расширении C для PHP, либо путем чтения вывода из сценария командной строки, называемого PHP. См. Также этот ответ .

О вашем требовании о том, чтобы цифры были последовательными – это действительно так важно? Это усложняет ситуацию. В противном случае вам было бы неплохо пойти с простым безопасным 6-байтовым случайным числом, закодированным в строку с использованием шестнадцатеричной кодировки (с 12-символьной строкой). Хотя я бы рекомендовал сделать это 10 байт и 20 символов, чтобы быть более безопасным.

Но если вы хотите быть последовательным, который я интерпретирую как монотонно увеличивающийся (поскольку простой +1 будет тривиально предсказуемым), это делает вещи намного сложнее. И вы ничего не получаете от этой сложности, единственное, что может случиться, это то, что вы нарушаете безопасность, изобретая неясную схему, которую легко использовать.

Мое предложение: добавьте еще один столбец, который действует как простой старый автоматически увеличиваемый идентификатор и добавит код как случайное число, сконструированное, как указано выше, как отдельный столбец. Насколько я вижу, нет необходимости требовать, чтобы код активации продукта был идентификатором одновременно.