Подтвердить что ты не робот

Как создать код/​​номер проверки?

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

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

Вот некоторые из требований:

  • Должно быть трудно ввести правильный случайный код
  • Должно быть трудно иметь действительный код, если я сделаю опечатку (перестановка цифр, неправильная цифра)
  • У меня должно быть разумное количество возможных комбинаций (скажем, 1М)
  • Код должен быть максимально коротким, чтобы избежать ошибок со стороны пользователя

Учитывая эти требования, как бы вы сгенерировали такое число?

РЕДАКТИРОВАТЬ:

@Haaked: код должен быть числовым, потому что пользователь набирает его на своем телефоне.

@matt b: на первом шаге код отображается на веб-странице, второй шаг - вызвать и ввести код. Я не знаю номер телефона пользователя.

Продолжение: я нашел несколько алгоритмов для проверки правильности чисел (см. Этот интересный проект Google Code: checkDigits).

4b9b3361

Ответ 1

После некоторых исследований я думаю, что я перейду к формуле ISO 7064 Mod 97,10. Он кажется довольно прочным, поскольку он используется для проверки IBAN (номер международного банковского счета).

Формула очень проста:

  • Возьмите число: 123456
  • Примените следующую формулу для получения контрольной суммы 2 цифры: mod(98 - mod(number * 100, 97), 97) = > 76
  • Конкатентное число и контрольная сумма для получения кода = > 12345676
  • Чтобы проверить код, убедитесь, что mod(code, 97) == 1

Тест:

  • mod(12345676, 97) = 1 = > ХОРОШЕЕ
  • mod(21345676, 97) = 50 = > BAD!
  • mod(12345678, 97) = 10 = > ПЛОХО!

По-видимому, этот алгоритм улавливает большинство ошибок.

Другим интересным вариантом был алгоритм Verhoeff. Он имеет только одну контрольную цифру и сложнее реализовать (по сравнению с простой формулой выше).

Ответ 2

Для 1M-комбинаций вам понадобятся 6 цифр. Чтобы убедиться, что нет никаких случайно действующих кодов, я предлагаю 9 цифр с вероятностью 1/1000, что случайный код работает. Я также предложил бы использовать другую цифру (всего 10) для выполнения проверки целостности. Что касается шаблонов распределения, то случайных будет достаточно, и контрольная цифра будет гарантировать, что одна ошибка не приведет к правильному коду.

Изменить: По-видимому, я не полностью прочитал ваш запрос. Используя номер кредитной карты, вы можете выполнить хэш на нем (MD5 или SHA1 или что-то подобное). Затем вы усекаете в соответствующем месте (например, 9 символов) и конвертируете в базу 10. Затем вы добавляете контрольную цифру (цифры), и это должно более или менее работать для ваших целей.

Ответ 3

Вы хотите сегментировать свой код. Часть его должна быть 16-битным CRC остальной части кода.

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

Затем вы префикс последовательности с CRC-16 этого порядкового номера и некоторого закрытого ключа. Вы можете использовать что-либо для закрытого ключа, если вы держите его в тайне. Сделайте это чем-то большим, по крайней мере GUID, но это может быть текст "Война и мир" из проекта Gutenberg. Просто нужно быть тайным и постоянным. Наличие закрытого ключа предотвращает возможность создания ключа, но использование 16-битного CR упрощает разбиение.

Чтобы проверить, что вы просто разделили число на две части, а затем возьмите CRC-16 порядкового номера и секретного ключа.

Если вы хотите еще больше затмить секвенциальную часть, разделите CRC на две части. Поместите 3 цифры спереди и 2 в конце последовательности (нулевая прокладка, чтобы длина CRC была согласованной).

Этот метод позволяет также начинать с меньших клавиш. Первые 10 ключей будут иметь 6 цифр.

Ответ 4

Должны ли быть только цифры? Вы можете создать случайное число от 1 до 1 М (я бы предложил еще более высокий), а затем Base32 encode it. Следующее, что вам нужно сделать, это Hash, что значение (используя значение секретной соли) и base32 кодирует хэш. Затем добавьте две строки вместе, возможно, разделенные тире.

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

Ответ 5

  • У меня должно быть допустимое количество возможных комбинаций (скажем, 1M)
  • Код должен быть как можно короче, чтобы избежать ошибок пользователя

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

Ответ 6

Когда вы создаете код подтверждения, у вас есть доступ к номеру телефона вызывающего абонента?

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

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

Конечно, это не сработает, если номер телефона, используемый на шаге 1, отличается от номера телефона, который вы вызываете на шаге 2.

Ответ 7

Предполагая, что вы уже знаете, как определить, какой ключ попал пользователь, это должно быть выполнимо достаточно легко. В мире безопасности существует понятие "одноразового" пароля. Это иногда называют "одноразовым паролем". Обычно они ограничены (легко типизируются) значениями ASCII. Итак, [a-zA-z0-9] и куча легко типизируемых символов. как запятая, период, полутень и скобки. В вашем случае, однако, вы, вероятно, захотите ограничить диапазон до [0-9] и, возможно, включить * и #.

Я не могу объяснить все технические детали того, как эти одноразовые коды генерируются (или работают) адекватно. За ним есть какая-то промежуточная математика, которую я бы мяснул, не рассмотрев сам сам. Достаточно сказать, что вы используете алгоритм для генерации потока одноразовых паролей. Независимо от того, как вы знаете предыдущие коды, последующий должен быть невозможно догадаться! В вашем случае вы просто будете использовать каждый пароль в списке как пользовательский случайный код.

Вместо того, чтобы не объяснять подробности реализации самостоятельно, я направлю вас на 9-страничную статью, где вы можете прочитать ее сами: https://www.grc.com/ppp.htm

Ответ 8

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

Есть несколько способов сделать это в прошлом.

  • Сделать открытый ключ и закрытый ключ. Кодируйте номера 0-999,999 с помощью закрытого ключа и раздайте результаты. Вам нужно будет ввести некоторые случайные числа, чтобы получить результат в более длинную версию, и вам нужно будет преобразовать результат из базы 64 в базовую 10. Когда вы получите введенный номер, преобразуйте его обратно в base64, применить закрытый ключ и посмотреть, не превышает ли промежуточные числа менее 1 000 000 (отбросить случайные числа).
  • Используйте обратную хеш-функцию
  • Используйте первый миллион номеров из PRN, высеянных с определенным значением. Функция "проверки" может получить семя и знать, что следующие миллионы значений являются хорошими. Он может генерировать их каждый раз и проверять один за другим при получении кода или при запуске программы хранить их все в таблице, сортировать, а затем использовать бинарный поиск (максимум для сравнения), поскольку миллион целых чисел не является целым пространства.

Существует множество других опций, но они распространены и легко реализуются.

-Adam

Ответ 9

Вы связались с проектом check digits, и использование функции "encode" кажется хорошим решением. В нем говорится:

encode может генерировать исключение, если к нему передаются "плохие" данные (например, нечисловые), а только возвращает true или false. Идея здесь заключается в том, что кодирование обычно получает данные из "надежных" внутренних источников (например, ключ базы данных), поэтому на самом деле это должно быть довольно обычным, исключительным, что передаются плохие данные.

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