Алгоритм для кодов подарочной карты

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

Давайте предположим, что я принимаю некоторый формат кода - говорят 10 символов от А до Я для простоты, и я начинаю генерировать ваучеры. Что корректный алгоритм должен сделать это?!

Мой первый подход должен пронумеровать все возможные коды от 0 до 308,915,776, затем начать генерировать случайные числа в том диапазоне. Это, очевидно, имеет большую проблему, хотя - я должен проверить свое случайное число по всем ранее сгенерированным оправдательным кодам и если оно сталкивается с существующим, я должен буду отбросить код и попробовать другого. Поскольку система накапливает больше данных, которые она замедлит. В экстремальном значении, когда существует только один код, уехал, для системы будет почти невозможно предположить это правильно.

Я мог предварительно генерировать все коды и переставить их, затем использовать их в порядке. Но это означает, что я должен сохранить много кодов, и на самом деле мое ключевое пространство больше, чем то, которое я описал, таким образом, мы говорим об очень большом объеме данных. Таким образом, это также не слишком желательно.

Таким образом, это оставляет меня с использованием кодов последовательно. Я не хочу отгадываемые оправдательные коды все же. У пользователя, который покупает ваучер "AAAAAAAAAY", не должно быть хорошего шанса получения другого действительного кода, если они вводят в "AAAAAAAAAZ".

Я могу переставить свой алфавит и свои положения так, чтобы вместо

'ABCDEFGHIJKLMNOPQRSTUVWXYZ' я использую

'LYFZTGKBNDRAPWEOXQHVJSUMIC'

и так, чтобы вместо положений

9 8 7 6 5 4 3 2 1 0 положения

1 8 0 7 5 4 3 9 2 6

Используя эту логику, учитывая код

LNWHDTECMA

следующий код был бы

LNEHDTECMA

Это - определенно менее отгадываемый путь. Но они - все еще только один символ прочь друг от друга, и данный всего два из этих ваучеров Вы знали бы, который увеличивает положение, и у Вас был бы 90%-й шанс получения следующего кода в 24 предположениях или меньше.

Мой "аварийный люк" должен угробить все это и пойти с GUID. У них есть больше символов, чем я хотел, чтобы мои пользователи должны были ввести и содержать подобные символы как I/1 и O/0, но они волшебно заставляют все вышеупомянутые головные боли уйти. Однако, я весело провожу время, думая об этом, возможно, Вы также. Я хотел бы услышать некоторые альтернативные предложения. Что Вы получили?

Спасибо!

20
задан Community 23 May 2017 в 12:33
поделиться

10 ответов

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

14
ответ дан 29 November 2019 в 23:27
поделиться

Это краткое изложение лучших битов всех остальных ответов. :)

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

  • уникальными
  • недоступными

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

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

2
ответ дан 29 November 2019 в 23:27
поделиться

Используйте N-битный серийный номер R, совмещенный с M-битным хэшем H конкатенированной пары (R, S), где S - некая секретная "соль" S, которую Вы НЕ публикуете . Затем кодируйте пару (R,H) буквенно-цифровым способом, который вам нравится. Если вам нравятся алгоритмы типа MD5* или SHA, но количество битов слишком велико, то просто возьмите M наименее значащих бит стандартного хэш-алгоритма.

Вы можете легко проверить: расшифровать алфавитно-цифровую кодировку, чтобы увидеть R и H. Затем вычислите H' = хэш(R+S) и убедитесь, что H = H'.

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

*перед тем, как кто-то скажет "MD5 сломан", позвольте мне напомнить вам, что известные слабые места MD5 - это атаки на столкновение, и не атаки на предимейдж . Также, используя неопубликованное, секретное значение соли, вы лишаете злоумышленника возможности проверить ваш механизм безопасности, если только он не сможет угадать значение соли. Если вы чувствуете себя параноиком, выберите два значения соли - Sprefix и Ssuffix, и вычислите хэш конкатенированной тройки (Sprefix,R,Ssuffix).

10
ответ дан 29 November 2019 в 23:27
поделиться

Можно использовать \@ backslashchar . Для меня работает следующее:

\documentclass{article}
\begin{document}
\newwrite\file
\immediate\openout\file=myfile.out
\makeatletter
\immediate\write\file{\@backslashchar}
\makeatother
\closeout\file
\end{document}
-121--2219339-

Обычно я делаю это следующим образом:

  1. Подключите кабель USB к компьютеру и установите карту SD на компьютере
  2. Получите файл APK где-нибудь на карте SD на телефоне
  3. Отключите карту SD на компьютере, позволяет телефону снова увидеть содержимое SD-карты
  4. Используйте Astro File Manager или какое-либо подобное приложение, чтобы перейти к этому файлу на SD-карте и выбрать его, , который предложит установить приложение на телефон.
-121--1410695-

Я бы сказал использовать «идеальный хеш» - http://en.wikipedia.org/wiki/Perfect_hash_function в сочетании с 4-значным случайным числом...

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

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

4
ответ дан 29 November 2019 в 23:27
поделиться

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

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

5
ответ дан 29 November 2019 в 23:27
поделиться

Programming Pearls имеет несколько примеров алгоритмов генерации множеств случайных чисел, с которыми стоит ознакомиться, если вас интересует подобная проблема.

В книге показано, что при генерации m случайных чисел со значением менее n, простой подход генерации чисел и выбрасывания дубликатов будет генерировать не более 2m случайных чисел if m < n / 2. Вот оно, на C++:

void gensets(int m, int n)
{
    set<int> S;
    set<int>::iterator i;
    while (S.size() < m) {
        int t = bigrand() % n;
        S.insert(t);
    }
    for (i = S.begin(); i != S.end(); ++i)
        cout << *i << "\n";
}

Очевидно, что если вы беспокоитесь о том, что люди будут угадывать значения, то вы захотите, чтобы m было намного меньше, чем n / 2.

Существует даже алгоритм, основанный на наборе, чтобы генерировать m случайные числа меньше n, при этом каждое значение будет одинаково вероятным, без дубликатов и с гарантией, что не будет генерироваться больше m случайных чисел:

void genfloyd(int m, int n)
{
    set<int> S;
    set<int>::iterator i;
    for (int j = n-m; j < n; j++) {
        int t = bigrand() % (j+1);
        if (S.find(t) == S.end())
            S.insert(t); // t not in S
        else
            S.insert(j); // t in S
    }
    for (i = S.begin(); i != S.end(); ++i)
        cout << *i << "\n";
}

Порядок чисел не является случайным, однако, это, вероятно, не лучший выбор для вас.

4
ответ дан 29 November 2019 в 23:27
поделиться

Я также ответил на другой вопрос: P

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

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

Например, с 8 символами у вас есть 1785793904896 возможных комбинаций, но если вы генерируете всего 1573 415 ваучеров, у вас будет 50% шанс иметь дубликат.

Итак, все зависит от того, сколько вы хотите генерировать, и максимальная длина кода вам удобно. Если вы генерируете много, и вы хотите сохранить его коротким, вы должны сохранить те, которые вы ранее сгенерировали, и проверяют базу данных для дубликатов.

2
ответ дан 29 November 2019 в 23:27
поделиться

Я думаю, что лучший способ пойти, это предложено Андреасом. Но мой ответ о интересном обсуждении.

Вы хотите создать последовательность чисел, которые вместе образуют перестановку s = {1, ..., max}. Один из способов сделать это - предпринять элементы циклической группы над S. Например, числа r = {x модуль p, x ^ 2 модуль p, x ^ 3 модуль p, ..., x ^ (P-1) Modulo P} образуют циклическую группу в течение {1, ..., P-1} , при условии P является Prime и X - это топливо для P . Поэтому, если вы выбираете MAX как простое число, вы используете эту последовательность.

Вы хотите «жестко-трещин» последовательность. Генератор для последовательности достаточно жесткой трещины называется PseudOrandom Generator (конечно, вам, вероятно, не нуждается в , что To-To-Track). Примером является последняя цифра элементов в r выше, предусмотрено P Секрет (я правильно?). Но ответ Andreas уже использует источник (псевдо-) случайные числа, поэтому нельзя назвать Pseudorandom Generator.

Если вы заинтересованы в Pseudorandom Generators, они подробно обсуждаются в томе 2 известной книги Knuth.

1
ответ дан 29 November 2019 в 23:27
поделиться

Вот только:

  • ID = каждый ваучер имеет уникальный (автоинкрементированный?) ID
  • CHECKSUM = применить N итераций алгоритма Verhoeff или Luhn на ID
  • VOUCHER = базовый преобразовать сгенерированный CHECKSUM из базы 10 в базу 36

См. также этот связанный с этим SO вопрос: Идеи для создания маленького (<10 цифр), не (очень) безопасного "хэша".


Одним из простых способов сделать этот метод более безопасным является использование неавтоинкрементированного значения ID, одним из вариантов может быть использование ID в качестве последних 6 или 7 цифр временной метки UNIX и вычисление контрольной суммы.

0
ответ дан 29 November 2019 в 23:27
поделиться

Я второе использование криптографических хеш-битов из MD5 очень просто. Чтобы сделать все читаемые, я ударил следующую идею: примите список слов и используете биты ключа, чтобы индексировать список слов. Мой список слов составляет около 100 000 слов, так что около 16 бит за слово, что для четырех слов дает 64-битный клавиш пространство. Результаты обычно довольно читаются.

Например, криптографическая подпись предыдущего абзаца представляет собой

Осредоточение особняка Хамиказына

(мой список слов наклонен к увеличению ключей; если вы хотите более короткие фразы, у вас меньше слов.)

Если у вас есть библиотека MD5, эта стратегия очень проста в реализации - я делаю это примерно в 40 линиях LUA.

0
ответ дан 29 November 2019 в 23:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: