Создание уникальных кодов в PHP/MySQL?

Я работаю с клиентом, которому нужно генерировать миллионы буквенно-цифровых кодов, используемых в журнальных скрещенных карточках, призах от бутылочной бутылки и т.д. Они должны быть достаточно короткими, чтобы печатать на кепке, они хотят удостовериться, что двусмысленные символы, такие как 1 и I, 0 и O и т.д., Не включены, и они должны быть явно сохранены для использования в будущем - t просто имеет алгоритм, который определяет "действительность", когда кто-то пытается его выкупить. Наконец, они хотят убедиться, что коды случайным образом распределены внутри большого "кодового пространства", чтобы люди не могли просто угадать дополнительные коды, прогуливаясь по алфавиту.

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

Ответы

Ответ 1

Если вам нужно около 10 миллионов уникальных ключей (например), лучший подход заключается в том, чтобы выбрать пространство ключа, которое экспоненциально больше, и начать произвольно генерировать. Читайте о Парадоксах дня рождения - это главное, о чем вам следует беспокоиться. Если вы хотите, чтобы 2 ^ n уникальных и безопасных ключей, убедитесь, что есть как минимум 2 ^ (2 * n) возможных значений. Здесь грубый алгоритм O (n log n):

  • Используйте ключевое пространство не менее 2 ^ 50 (так, другими словами, допустим 2 ^ 50 возможных уникальных значений), и у вас будут едва ли какие-либо коллизии во всем наборе данных - и любой, кто грубо заставляет ваши ключи имеют примерно равные шансы получить ключ, если они попробуют 2 из 25 из них.
  • генерировать столько случайных чисел, сколько вам нужно
  • индексировать базу данных на вашем ключе (это шаг O (n lg n): сортировка)
  • через БД и перебрать весь набор данных, чтобы обрезать дубликаты (псевдокод ниже)
  • Удалите повторяющиеся строки, и все готово.

псевдокод:

$last = null;
while ($current = getnext()) {
    if ($last == $current) {
        push($toDelete, $current);
    }
    $last = $current;
}

Ответ 2

Предположим, вы можете использовать набор символов, например, 40 символов однозначных верхних, нижних и числовых символов.

Для последовательности n символов у вас есть 40 n комбинаций

  • 40 4= 2,560,000
  • 40 5= 102 400 000
  • 40 6= 4096 000 000
  • 40 7= 163 840 000 000
  • 40 8= 6 553 600 000 000

Таким образом, 8 символов дают довольно хорошее пространство для работы - если вы создали 10 миллионов кодов, вам придется попробовать сотни тысяч комбинаций для перебора кода.

Или вы приходите с другого направления - укажите количество возможных кодов, сколько кодов вы должны генерировать, чтобы избежать ловушки, которую они называют День рождения Парадокс?

Принимая код 8 char, 6 553 600 000 000 составляет примерно 2 42 поэтому вы можете разумно генерировать 2 21 коды из него или 2,097,152

Ответ 3

Использовать алгоритм одноразового пароля?

RFC4225 подробно описывает алгоритм HMAC.

http://www.ietf.org/rfc/rfc4226.txt

но вместо использования кодировки base10 0-9 используйте base32.

Ответ 4

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

Ответ 5

Как ни странно, со следующим семенем я смог генерировать только 32 уникальные строки.

ABCDEFGHJKLMNPQRSTUVWXYZ23456789

С более длинным семенем я смог сгенерировать еще много созданных 40 000 уникальных строк.

ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789