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

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

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

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

Мне нужен простой алгоритм, который может принимать последовательные числа и генерировать уникальные, не последовательные ключи из 16-20 буквенно-цифровых символов.

UPDATE

SHA-1 выглядит как лучший способ. Однако то, что я вижу из образца вывода ключей SHA-1, состоит в том, что они довольно длинны (40 символов). Получил бы ли я достаточные результаты, если бы я взял 40 char и, скажем, усекал все, кроме последних 16 символов?

Ответы

Ответ 1

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

Кстати, чтобы сохранить счетчик символов, я бы предложил использовать base64 в качестве кодировки после хэширования.

SHA-1 выглядит как лучший способ. Однако то, что я вижу из образца вывода ключей SHA-1, состоит в том, что они довольно длинны (40 символов). Получил бы ли я достаточные результаты, если бы взял результат 40 char и, скажем, усекал все, кроме последних 16 символов?

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

Hex:    a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
Base64: qUqP5cyxm6YcTAhz05Hph5gvu9M

--- редактировать ---

Собственно, @Nick Johnson утверждает с убедительными аргументами, что хэши могут быть усечены без значительных последствий для безопасности (очевидно, увеличивая вероятность двойных столкновений за каждый бит, который вы бросаете).

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

Конструкция спецификации HMAC была обусловлена ​​существованием атаки на более тривиальные механизмы для объединения ключа с хешем функция. Например, можно предположить ту же безопасность, что и HMAC может быть достигнуто с помощью MAC = H (сообщение ключа ∥). Однако это метод страдает от серьезного недостатка: с большинством хеш-функций он легко добавлять данные в сообщение, не зная ключа и получать другой действующий MAC. Альтернатива, добавление ключа с использованием MAC = H (клавиша сообщения ∥), страдает от проблемы, что злоумышленник, который может найти столкновение в (без ключа) хэш-функции имеет столкновение в MAC. Использование MAC = H (клавиша ∥ сообщение ∥) лучше, однако различные документы безопасности предлагали уязвимости с таким подходом, даже если используются две разные клавиши.

Более подробную информацию о последствиях безопасности как этого, так и сокращения длины см. в разделах 5 и 6 RFC2104.

Ответ 2

Один из вариантов - использовать хэш, как описывает Маттео.

Другим является использование блочного шифрования (например, AES). Просто выберите случайное значение nonce и вызовите шифр в режиме счетчика, используя ваши серийные номера в качестве счетчика.

Конечно, это сделает ключи обратимыми, что может быть или не быть желательным свойством.

Ответ 3

Вы можете использовать генератор Xorshift random number для генерации уникального 64-битного ключа, а затем закодировать этот ключ, используя любую желаемую схему. Если вы используете base-64, ключ имеет длину 11 символов. Если вы используете шестнадцатеричное кодирование, ключ будет длиной 16 символов.

XSSHift RNG - это в основном просто бит-микшер, и есть версии с гарантированным периодом 2 ^ 64, что означает, что он гарантированно генерирует уникальное значение для каждого входа.

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