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

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

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

11.12.2008 13:29:09
Что бы вы ни пытались, если ваше приложение должно расшифровать ваш файл лицензии, каждый поощренный пользователь может сделать это. Подумайте о другом способе лицензирования вашего софта.
Oliver Friedrich 29.10.2009 11:29:26
9 ОТВЕТОВ
РЕШЕНИЕ

Похоже, вы хотите использовать публичную / частную криптографию для подписи токена лицензии (например, фрагмент 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 умрет с исключением из-за безопасности, поскольку строгое имя больше не будет соответствовать самой сборке.

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

    /// <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, а затем проверить его с помощью открытого ключа сборки.

Обновить

Добавлен актуальный пост в блоге с хорошим подробным просмотром файлов лицензий.

39
14.11.2013 21:18:37
Чрезвычайно полезный код шифрования. Спасибо, Wolfwyrd, за то, что сделали его доступным.
Matt Crouch 3.04.2009 16:19:50
@Wolfwyrd: Утилиты, которые вы сделали доступными, не могли бы вы дать краткие инструкции о том, как их использовать?
Ian 11.03.2010 12:39:35
@Wolfwyrd: ссылка на ваш класс больше не действительна. Мне очень хотелось увидеть процесс, который вы использовали для некоторых из этих функций. Есть ли шанс, что вы можете исправить ссылку?
Molloch 5.07.2011 04:55:14
@Molloch - Загруженные файлы в Snipt, где они должны пережить мою неуклюжую чистку сервера :)
Wolfwyrd 6.07.2011 15:16:58
Я нашел этот проект на GitHub, я посмотрел на метод EncryptionUtils.GetRSAParameters(key), он очень сложный ... мы не можем просто создать KeyContainerName из байтового массива открытого ключа сборки? cspParameters.KeyContainerName = FromArrayToString(pubKey);?
mshwf 2.09.2018 13:47:17

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

1
11.12.2008 13:36:28

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

0
11.12.2008 13:41:20
Вы имеете в виду серийный номер диска С, верно? не содержание. И убедитесь, что вы не используете идентификатор тома, который можно легко скопировать.
Martin 11.12.2008 14:15:50
Хэширование диска - плохая идея - слишком много данных. Лучше использовать DPAPI (область видимости машины) для защиты GUID (только создавать, если он еще не существует) в качестве «идентификатора машины». Используйте DPAPI пользовательской области для защиты «идентификатора пользователя».
devstuff 15.12.2008 05:32:43

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

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

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

1
11.12.2008 13:53:20

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

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

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

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

7
11.12.2008 14:05:03
Я нашел материалы MSDN, о которых вы говорили, и подпись XML выглядит достаточно просто. Тем не менее, не могли бы вы рассказать подробнее о части вашего ответа с открытым / закрытым ключом? Я ничего не видел об использовании двух разных ключей для подписи и проверки XML-файла.
David Brown 11.12.2008 15:30:40
используйте 'sn -k' для создания пары ключей. Эта пара ключей используется для подписи XML. Чтобы проверить XML, вы используете публичную часть. Не включайте весь ключ в свой код. Используйте sn -p для извлечения публичной части в файл. Используйте это в своем коде, который вы распространяете для проверки лицензии.
Frans Bouma 11.12.2008 16:19:04

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

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

-1
25.08.2009 12:53:18

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

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

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetRSAFromSnkFile(keyFilePath);

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

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

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

1
22.08.2009 20:19:15

Ответ 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;
}
6
29.10.2009 11:25:29

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

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

0
7.11.2009 07:18:37