Как создать проверочный код/номер?

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

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

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

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

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

EDIT:

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

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

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

9 ответов


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

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

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

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

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


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

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

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

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

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

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


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

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


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

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


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

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

о хэшировании, я не уверен если можно взять 10-значное число и выйти с хэш-результатом, который будет

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


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

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

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


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

Существует несколько способов, которыми люди делали это в прошлом.

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

есть куча других вариантов, но они являются общими и легко реализовать.

Адам


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

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

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