Лицензионные ключи для своего софта: как устроена проверка
· 4 мин чтения · MTB Digital
Продавать свою программу по ключу кажется простым: выдал строку XXXX-XXXX, программа проверила её на сервере — готово. На деле первая же наивная проверка ломается за вечер: ответ сервера подделывают, ключ копируют на десять компьютеров, а программа перестаёт работать у честного покупателя, когда у него пропал интернет. Расскажем, как устроена проверка лицензий в нашем каталоге и почему именно так.
Ключ, активация и токен
Ключ — то, что покупатель видит в кабинете: MTBD-7K4Q-9TXM-2HWE. В ключах нет букв и цифр, которые легко перепутать (I и 1, O и 0), — их диктуют по телефону и переписывают с экрана.
Активация — привязка ключа к конкретному устройству или установке. Сколько активаций даёт тариф, написано на странице продукта; покупатель видит в кабинете, где ключ используется, и может сбросить активацию сам — например, при переезде на новый сервер.
Отпечаток устройства (fingerprint) — стабильная строка, которую программа вычисляет сама: из идентификатора машины, домена сайта, другой характеристики, которая не меняется от запуска к запуску. Именно по нему сервер понимает, что это то же устройство.
Токен активации — то, что программа получает при первой активации и дальше использует вместо ключа. Повторная активация с тем же отпечатком выдаёт новый токен, старый перестаёт работать.
Почему ответ сервера подписан
Если программа просто спрашивает сервер «ключ рабочий?» и верит ответу {"status": "active"}, такой ответ подделывается подменой адреса сервера или перехватом трафика. Поэтому каждый ответ нашего API лицензий подписан.
Ответ выглядит так (сокращено):
{
"payload": "{\"activationToken\":\"…\",\"expiresAt\":null,\"fingerprint\":\"pc-1\",\"issuedAt\":\"2026-10-23T12:00:00.000Z\",\"nonce\":\"…\",\"product\":\"bot\",\"status\":\"active\"}",
"signature": "<base64, Ed25519>"
}
payload — это строка с JSON, ключи которого отсортированы и без пробелов. Подпись Ed25519 считается над байтами этой строки. Закрытый ключ хранится только на сервере, а открытый вшивается в программу. Подделать ответ, не зная закрытого ключа, нельзя.
Важная деталь: проверять подпись нужно над строкой ровно в том виде, в каком она пришла. Если сначала разобрать JSON, а потом собрать заново, порядок ключей или пробелы могут измениться — и подпись не сойдётся.
Пример проверки на Python с библиотекой cryptography:
import base64
import json
from cryptography.hazmat.primitives.serialization import load_pem_public_key
PUBLIC_KEY = load_pem_public_key(open("license-public.pem", "rb").read())
def verified_payload(answer: dict) -> dict:
payload = answer["payload"]
# Бросает InvalidSignature, если ответ подделан или изменён.
PUBLIC_KEY.verify(base64.b64decode(answer["signature"]), payload.encode("utf-8"))
return json.loads(payload)
Что проверить после подписи
Подпись гарантирует, что ответ выдал наш сервер. Но выдать его могли другому устройству или давно. Поэтому дальше программа проверяет по порядку:
productсовпадает с продуктом самой программы — ответ для другого продукта не подходит.fingerprintсовпадает с отпечатком этого устройства — так не сработает скопированный с другого компьютера токен.nonceсовпадает с отправленным. Программа посылает случайную строку, сервер возвращает её внутри подписанного ответа — это защита от повтора старого ответа.issuedAtне старше трёх суток и не из будущего (с запасом в несколько минут на неточные часы). Иначе можно сохранить ответ «active» и подсовывать его после того, как подписка приостановлена.- И только потом
status:active— работать;past_due— работать и предупредить, что оплата не прошла;suspendedиrevoked— закрыть доступ.
Когда нет связи
Честный покупатель не должен страдать из-за того, что у него пропал интернет или наш сервер недоступен. Поэтому:
- программа проверяет лицензию раз в сутки, а последний успешный подписанный ответ хранит у себя;
- сохранённый ответ действует до трёх суток — этого хватает, чтобы пережить сбой связи;
- ответы с ошибками не подписаны, и по ним программа не делает ничего необратимого: не удаляет токен и не сбрасывает настройки. Она показывает сообщение и повторяет попытку позже. Иначе любой, кто может подменить ответ, отключил бы программу у пользователя.
Что делать, если связи нет дольше трёх суток, решает сам продукт: одна программа может продолжить работу в ограниченном режиме, другой без проверки лучше остановиться.
Ограничения, о которых стоит знать
Любую проверку в программе, которая работает на чужом компьютере, можно обойти, если очень постараться: исправить код и убрать проверку совсем. Лицензирование защищает не от этого, а от массового копирования ключей и подделки ответов без правки программы. Поэтому важно, чтобы честному покупателю было удобнее заплатить: обновления и плагины к программе выдаются только по действующей лицензии.
По этой схеме работают программы из нашего каталога. Если вам нужно такое же лицензирование для своего софта — опишите задачу.
Ещё статьи
- Как принимать оплату на форуме XenForo: способы и что выбратьПлатные группы в XenForo, почему встроенные PayPal и Stripe не подходят в России, агрегаторы, эквайринг банка и чеки 54-ФЗ — что выбрать для своего форума.
- Плагины FunPay Cardinal: как устанавливать безопасноПлагин Cardinal — это код с доступом к вашему аккаунту FunPay. Как проверить плагин до установки, что искать в коде и что делать, если ключ утёк.
- Telegram-бот для платного канала: Stars или оплата картойПравила Telegram для цифрового, подписка на канал за Stars и оплата картой на сайте: приглашения, продление, удаление, чеки 54-ФЗ и персональные данные.