2008-12-11 2 views
20

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

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

+2

Независимо от того, что вы пытаетесь, если вашему приложению необходимо расшифровать файл лицензии, каждый пользователь может это сделать. Подумайте о другом способе лицензирования вашего программного обеспечения. – 2009-10-29 11:29:26

ответ

37

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

Update

Добавлена ​​up to date blog post с красивым подробным пробегают на лицензионных файлов

1

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

0

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

+0

Вы имеете в виду серийный номер привода C справа? а не содержание. И убедитесь, что вы не используете идентификатор тома, который можно легко скопировать. – Martin 2008-12-11 14:15:50

+0

Хеширование диска - плохая идея - слишком много данных. Лучше использовать DPAPI (машинный объем) для защиты GUID (только создать, если он еще не существует) как «идентификатор машины». Используйте DPAPI для пользовательского интерфейса для защиты «идентификатора пользователя». – devstuff 2008-12-15 05:32:43

1

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

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

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

7

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

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

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

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

+0

Я нашел материалы MSDN, о которых вы говорили, и подписание XML выглядит достаточно просто. Однако не могли бы вы еще подробнее рассказать о части ответа на публичный/частный ключ? Я ничего не видел об использовании двух разных ключей для подписи и проверки файла XML. – 2008-12-11 15:30:40

+0

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

-1

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

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

1

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

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

RSACryptoServiceProvider rsaKey = EncryptionUtils.GetRSAFromSnkFile(keyFilePath); 

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

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

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

5

Ответы 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; 
} 
0

При реализации вашей подписи кода/проверки, будьте осторожны, чтобы не поставить его в отдельную сборку. Защита доступа к кодам Защита от несанкционированного доступа теперь очень легко обойти, как объясняется в статье CAS Tamper-Proofing is Broken: Consequences for Software Licensing.

Обязательная оговорка & plug: компания, которую я учредил, производит OffByZero Cobalt licensing solution.

Смежные вопросы