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