Генерация уникальных кодов в PHP / MySQL?

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

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

5 ответов


Если вам нужно около 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;
}

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

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

  • 404 = 2,560,000
  • 405 = 102 400 000
  • 406 = 4,096,000,000
  • 407 = 163,840,000,000
  • 408 = 6,553,600,000,000

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

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

взяв 8 Чаре код, 6,553,600,000,000 составляет приблизительно 242, таким образом, вы можете создать 221 коды от него, или 2,097,152


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

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

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

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


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


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

ABCDEFGHJKLMNPQRSTUVWXYZ23456789

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

ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789ABCDEFGHJKLMNPQRSTUVWXYZ234567892345678923456789