Эффективный метод шифрования файла лицензии?

Для веб-приложения я хотел бы создать простую, но эффективную систему лицензирования. В C# это немного сложно, так как мой метод дешифрования может быть просмотрен любым, у кого установлен Reflector.

Какие методы шифрования файлов на C# достаточно защищены от несанкционированного доступа?

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

Oliver Friedrich 29.10.2009 14:29
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
22
1
13 341
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Зачем вам нужно его шифровать? Если вы боитесь, что это подделка (например, кто-то увеличивает количество пользователей), не могли бы вы просто подписать его, например, цифровой сертификат вашей организации?

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

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

Martin 11.12.2008 17:15

Хеширование диска - плохая идея - слишком много данных. Лучше использовать DPAPI (машинная область) для защиты GUID (создавать только в том случае, если он еще не существует) в качестве «идентификатора машины». Используйте DPAPI пользовательской области для защиты «идентификатора пользователя».

devstuff 15.12.2008 08:32

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

Все остальные методы требуют больше времени и, следовательно, больше денег для реализации, поскольку взламывают и злоупотребляют вашим программным обеспечением вместо покупки лицензии.

.NET имеет несколько хороших криптографических классов, но, как вы упомянули, если вы кодируете кодировку / дешифрование лицензии, каждый может легко ее декомпилировать.

Используйте подписанный XML-файл. Подпишите его с помощью части закрытого ключа пары ключей и проверьте ее с помощью части открытого ключа в своем программном обеспечении. Это дает вам возможность проверить, была ли изменена лицензия, а также проверить, действителен ли файл лицензии.

Подписание и проверка подписанного файла XML задокументированы в MSDN.

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

Конечно, люди могут вырезать / взломать вашу распределенную сборку и вырвать проверку xml-знака, но, опять же, они всегда смогут это сделать, независимо от того, что вы делаете.

Я обнаружил, что материалы MSDN, о которых вы говорили, и подписывание XML выглядят достаточно просто. Однако не могли бы вы подробнее рассказать о части вашего ответа, связанной с открытым / закрытым ключом? Я ничего не видел об использовании двух разных ключей для подписи и проверки XML-файла.

David Brown 11.12.2008 18:30

используйте sn -k для создания пары ключей. Эта пара ключей используется для подписи XML. Чтобы проверить XML, вы используете публичную часть. Не включайте в свой код весь ключ. Используйте sn -p для извлечения публичной части в файл. Используйте это в своем коде, который вы распространяете, для проверки лицензии.

Frans Bouma 11.12.2008 19:19
Ответ принят как подходящий

Похоже, вы хотите использовать публичную / частную криптографию для подписи токена лицензии (например, XML-фрагмента или файла), чтобы вы могли обнаружить подделку. Самый простой способ справиться с этим - выполнить следующие действия:

1) Создайте пару ключей для своей компании. Вы можете сделать это в командной строке Visual Studio с помощью инструмента SN. Синтаксис:

sn -k c:\keypair.snk

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

3) Создайте лицензию для своего клиента, это должен быть документ XML, и подпишите его своим закрытым ключом. Это включает в себя простое вычисление цифровой подписи, и шаги по его выполнению можно найти по адресу:

http://msdn.microsoft.com/en-us/library/ms229745.aspx

4) На клиенте при проверке лицензии вы загружаете XmlDocument и используете свой открытый ключ для проверки подписи, чтобы доказать, что лицензия не была подделана. Подробности о том, как это сделать, можно найти по адресу:

http://msdn.microsoft.com/en-us/library/ms229950.aspx

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

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

    /// <summary>
    /// Retrieves an RSA public key from a signed assembly
    /// </summary>
    /// <param name = "assembly">Signed assembly to retrieve the key from</param>
    /// <returns>RSA Crypto Service Provider initialised with the key from the assembly</returns>
    public static RSACryptoServiceProvider GetPublicKeyFromAssembly(Assembly assembly)
    {
        if (assembly == null)
            throw new ArgumentNullException("assembly", "Assembly may not be null");

        byte[] pubkey = assembly.GetName().GetPublicKey();
        if (pubkey.Length == 0)
            throw new ArgumentException("No public key in assembly.");

        RSAParameters rsaParams = EncryptionUtils.GetRSAParameters(pubkey);
        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(rsaParams);

        return rsa;
    }

Я загрузил образец класса с множеством полезных утилит шифрования на Snipt по адресу: http://snipt.net/Wolfwyrd/encryption-utilities/, чтобы помочь вам встать на путь.

Я также включил образец программы по адресу: https://snipt.net/Wolfwyrd/sign-and-verify-example/. Пример требует, чтобы вы добавили его в решение с библиотекой утилит шифрования и предоставили тестовый файл XML и файл SNK для подписи. Проект должен быть подписан с помощью созданного вами SNK. Он демонстрирует, как подписать тестовый XML-файл с помощью закрытого ключа из SNK, а затем проверить с помощью открытого ключа сборки.

Обновлять

Добавлен последнее сообщение в блоге с красивым подробным прохождением файлов лицензий.

Чрезвычайно полезный код шифрования. Спасибо Wolfwyrd за то, что сделали его доступным.

Matt Crouch 03.04.2009 20:19

@Wolfwyrd: Утилиты, которые вы сделали доступными, не могли бы вы дать краткие инструкции по их использованию?

Ian 11.03.2010 15:39

@Wolfwyrd: ссылка на ваш класс больше не действительна. Мне очень хотелось увидеть процесс, который вы использовали для некоторых из этих функций. Есть шанс исправить ссылку?

Molloch 05.07.2011 08:55

@Molloch - Загрузил файлы в Snipt, где они должны пережить мою неуклюжую чистку сервера :)

Wolfwyrd 06.07.2011 19:16

Я нашел этот проект на GitHub, я посмотрел на метод EncryptionUtils.GetRSAParameters(key), он очень сложный ... не можем ли мы просто создать KeyContainerName из байтового массива открытого ключа сборки? cspParameters.KeyContainerName = FromArrayToString(pubKey);?

mshwf 02.09.2018 16:47

RE: Не включайте в свой код весь ключ. Используйте sn -p для извлечения публичной части в файл. Используйте это в своем коде, который вы распространяете, для проверки лицензии.

Используя код из статей MSDN, я создал небольшое приложение (LicMaker), чтобы облегчить это. Приложение подписано полной парой ключей. Входными данными является неподписанный файл лицензии в формате .XML. Результатом является исходная подпись XML + в подписанном файле .LIC. Мой продукт также подписан тем же файлом полной пары ключей. Продукт проверяет, не был ли изменен файл .LIC. Работает отлично. Я не использовал sn -p для этого решения.

Похоже, что в образцах MSDN используются параметры по умолчанию, и это приводит к подписанию для конкретной машины, так что вы не можете подписаться на одной машине и проверить на произвольной другой машине. Я изменил логику в этих примерах, чтобы использовать ключи в моем snk на подписывающей машине и ключи из моей сборки на проверяющей машине. Это было сделано с использованием логики из образца MSDN и подпрограмм из (очень хорошо выполненного) образца ExcryptionUtils.cs, ссылка на который приведена выше.

Для подписи файла я использовал это:

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetRSAFromSnkFile(keyFilePath);

Для проверки файла я использовал это:

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetPublicKeyFromAssembly
   (System.Reflection.Assembly.GetExecutingAssembly());

Кстати: я заметил, что проверка подписи XML игнорирует комментарии XML.

Ответ Wolfwyrd превосходен, но я просто хотел предложить намного более простую версию метода Wolfwyrd GetPublicKeyFromAssembly (который использует множество вспомогательных методов из библиотеки, любезно предоставленной Wolfwyrd).

В этой версии это весь код, который вам нужен:

/// <summary>
/// Extracts an RSA public key from a signed assembly
/// </summary>
/// <param name = "assembly">Signed assembly to extract the key from</param>
/// <returns>RSA Crypto Service Provider initialised with the public key from the assembly</returns>
private RSACryptoServiceProvider GetPublicKeyFromAssembly(Assembly assembly)
{
    // Extract public key - note that public key stored in assembly has an extra 3 headers
    // (12 bytes) at the front that are not part of a CAPI public key blob, so they must be removed
    byte[] rawPublicKeyData = assembly.GetName().GetPublicKey();

    int extraHeadersLen = 12;
    int bytesToRead = rawPublicKeyData.Length - extraHeadersLen;
    byte[] publicKeyData = new byte[bytesToRead];
    Buffer.BlockCopy(rawPublicKeyData, extraHeadersLen, publicKeyData, 0, bytesToRead);

    RSACryptoServiceProvider publicKey = new RSACryptoServiceProvider();
    publicKey.ImportCspBlob(publicKeyData);

    return publicKey;
}

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

Обязательный отказ от ответственности и заглушка: компания, которую я учредил, производит Решение для лицензирования OffByZero Cobalt.

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