Схема генерации серийного номера бедного человека, часть 2
Это продолжение моего предыдущего вопроса здесь:
Схема генерации серийного номера бедного человека
Допустим, я сгенерировал пару секретный / открытый ключ, но я хочу сохранить закрытый ключ в самом зарегистрированном приложении - например, путем генерации кода.c, который содержит только данные (части открытого и закрытого ключей).
Конечно, это рискованное решение - поскольку, если хакер извлекает закрытый ключ из приложения, он может создавать лицензии самостоятельно.
Но это "решение для бедных", поэтому я хочу, чтобы все было в одном приложении - закрытый и открытый ключи - чтобы форма регистрации была бы также диалоговым окном генерации серийного номера.
Поэтому я хочу поместить закрытый ключ в приложение, но защитить его паролем, о котором знаю только я.
Таким образом, вводя серийный номер - при первом проходе мы пытаемся сопоставить определенное оборудование (проверить подпись), но если это не удается, мы пытаемся проверить, является ли конечный пользователь "администратором" (или человеком, генерирующим серийный номер).
Какой будет наилучший алгоритм двустороннего шифрования, который будет использовать пароль в качестве входных данных и будет терпимым к атакам методом перебора?
Я предполагаю, что "пароль администратора" должен быть достаточно надежным, чтобы его нельзя было легко угадать (его нет ни в одном из хорошо известных словарей взлома).
Также было бы хорошо хранить пароль в реестре / или хотя бы в зашифрованном виде. Возможно, имеет смысл ввести пароль === sha-1 hash ===> 20-байтовый хэш - сохранить его в реестре ("пароль администратора"), а затем использовать хэш для шифрования закрытого ключа.
Та же проблема, что и в предыдущем вопросе. В качестве основы я бы предпочел использовать простой C или C++ (не C#), предпочтительно Windows / wincrypt.h или любой существующий простой исходный код на C (желательно не огромные сторонние библиотеки).
2 ответа
Предостережения:
- Это не столько ответ на прямой вопрос о заданном алгоритме шифрования, сколько о вашей общей цели, основанной на ваших двух опубликованных вопросах, ответах и комментариях.
- Хотя я в общем и целом слежу за проблемами безопасности программного обеспечения, я не эксперт, поэтому примите все, что я скажу здесь, соответственно.
Вы пытаетесь защитить свое программное обеспечение. То есть то, что вы ищете, - это способ реализации схемы лицензирования.
То, что вам нужно [и, надеюсь, есть], но не опубликовано, - это функциональная / проектная спецификация для этого. Двустороннее шифрование является лишь частью этого.
Вы не первый человек, который нуждается в этом. Уже есть схемы, чтобы сделать это. Я бы порекомендовал использовать существующее решение. Вероятно, существует публичная / бесплатная версия с открытым исходным кодом.
Вы говорили об электронной почте, регистрационной форме и вырезании и вставке, но не рассказали, как это работает. Вы также не упомянули, как это взаимодействует с вашим приложением. Вы регистрируетесь в веб-браузере или в приложении есть диалоговое окно регистрации?
Я предполагаю, что у вас есть пользователь, введите адрес электронной почты в форму. Затем ваш сервер отправит обратно электронное письмо с некоторым специальным кодом (например, действительным в течение 15 минут), который пользователь должен ввести для завершения регистрации, чтобы подтвердить, что электронное письмо является действительным, вместе с идентификационной информацией системы.
Вы упомянули, что вырезать и вставить является ограничивающим фактором. Но, IMO, это не совсем так, как вы можете поместить ключ в MIME-кодированное вложение и сделать так, чтобы пользователь сохранил его в файл. Регистрационная форма может загрузить этот файл. Даже длинное значение (например, 10 строк по 72 символа / строка) будет по-прежнему помещаться в буфер обмена.
Вы собираете [надеюсь] уникальную идентифицирующую информацию о клиентской системе. Серийный номер процессора теперь равен 0 на большинстве процессоров после Pentium-III [если не включен в BIOS]. Но, другие CPUID
части могут обеспечить некоторую уникальность. MAC-адрес Ethernet уникален, но многие сетевые адаптеры позволяют изменять его программно. Серийный номер диска не является хорошим выбором [IMO], потому что диски имеют наивысшую частоту отказов и требуют замены со временем.
Но давайте предположим, что вы можете собрать достаточно информации из вышеперечисленных источников [и, возможно, некоторых других], чтобы получить "системный идентификатор". Вы можете объединить это с другими вещами, такими как имя пользователя и т. Д. Вы можете запустить это через односторонний хеш, например, sha1 [или любой другой], если хотите. Итак, теперь у вас есть "системная идентификация". Сохраните это где-нибудь (например, файл или реестр)
Но хранение закрытого ключа в приложении [или в любом месте клиентской системы] не является началом, IMO. Это нужно только на этапе генерации.
Итак, попросите процесс регистрации отправить идентификатор системы на частный сервер, которым вы управляете (например, Amazon EC2). Сервер зашифровывает / подписывает [используя криптографию с открытым / закрытым ключом, как RSA] системную идентификацию и отправляет обратно открытый ключ и "подписанный результат". Эти хранятся.
Проверка для любого приложения состоит в том, чтобы собрать информацию об идентификаторе системы, применить алгоритм и открытый ключ. Он должен соответствовать подписанному результату.
Это устраняет необходимость хранить закрытый ключ в приложении, хранить его в зашифрованном виде с помощью пароля, который использует RC4 [или эквивалент]. Это устраняет сложности, которые в первую очередь ослабили вашу защиту.
Я немного запутался в "системном администраторе" или "серийном генераторе лицензии". Если это не вы [или ваш сервер], это означает, что вы собираетесь выдавать OEM-контракты, и местный администратор может создавать лицензии для данного поднабора систем под этим контролем. Итак, вам понадобится OEM-ключ [который отправляется на ваш сервер], чтобы можно было генерировать несколько лицензий.
Теперь плохие новости.
Любая схема лицензирования программного обеспечения [легко] может быть взломана. В приложении, независимо от того, насколько сложным [или простым] является алгоритм проверки, оно сводится к [или множественным] тестам go / nogo. То есть что-то вроде:
#include <stdlib.h>
int user_authorized(void);
void run_program();
int
main(void)
{
if (! user_authorized())
abort();
run_program();
return 0;
}
Это переводится как:
.globl main
main:
subq $8, %rsp
call user_authorized
testl %eax, %eax
je .L5 # change this to a nop
xorl %eax, %eax
call run_program
xorl %eax, %eax
addq $8, %rsp
ret
.L5:
call abort
Обратите внимание на je .L5
прервать программу. Если программа пропатчена, чтобы изменить эту инструкцию на nop
Лицензионный тест "проходит", независимо от того, что user_authorized
делает.
Это может быть повторено для столько проверок безопасности, сколько имеет программа.
Безопасность это относительный термин. Приложение за 50 долларов не нуждается в такой же защите, как приложение, которое продается за 500000 долларов (например, некоторые программы CAD/CAE от Xilinx).
Возьмите лист из книги игр Microsoft. Они представляют диалоговое окно "лицензирование", которое вы должны принять (например, "термоусадочная пленка"). Нужно принять соглашение. Он запрещает обратный инжиниринг и т. Д. Это дает вам юридическое прикрытие Проконсультируйтесь с адвокатом по этому вопросу.
Это, в дополнение к любой программной схеме, которую вы в конечном итоге решите.
Ответ на этот вопрос здесь:
Схема генерации серийного номера бедного человека
В моем собственном прототипе я использую алгоритм потокового шифрования RC4 для двустороннего шифрования.
Это надежно? Может кто-нибудь взломать это?!