Вопрос

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

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

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

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

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

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

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

@Мэтт Б:На первом этапе код отображается на веб-странице, на втором этапе необходимо позвонить и ввести код.Я не знаю номер телефона пользователя.

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

Это было полезно?

Решение

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

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

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

Тест :

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

Судя по всему, этот алгоритм улавливает большую часть ошибок.

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В прошлом люди делали это несколькими способами.

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

Есть множество других вариантов, но они распространены и просты в реализации.

-Адам

Вы связались с контрольные цифры проект, и использование функции «кодировать» кажется хорошим решением.Там говорится:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top