Создание уникальных кодов в 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