Лицензия на настольное приложение C # - PullRequest
29 голосов
/ 02 сентября 2010

Как я могу добавить лицензию на свое настольное приложение C #? Мне нужно найти подходящий бесплатный метод для предотвращения установки моего программного обеспечения неавторизованными пользователями.

Ответы [ 5 ]

56 голосов
/ 30 мая 2011

Я, вероятно, немного опоздал, но я потратил немного времени, пытаясь разработать быстрый и эффективный метод защиты небольшого приложения на C #, и я хотел бы поделиться своими результатами.

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

Очевидно, что нет ничего пуленепробиваемого, когда речь заходит о защите программного обеспечения (Это все равно, что защитить свой дом от грабителей: тревоги, лай собак и заборы создают больше проблем, чем оно того стоит, но они не остановят кого-то решительногочтобы войти)

Таким образом, ключевая фраза в защите программного обеспечения - создать больше проблем, чем того стоит: если вы предлагаете ERP-систему за 1 000 000 долларов, вы хотели бы иметь действительно хорошую защиту, разрешенную через веб-сайт.услуга (и пользователи, которые платят так много за систему, не будут иметь проблем с предоставлением этой системе постоянного доступа в Интернет)

Однако, если вы платите всего лишь 5-30 долларов за маленькое приложение, пользователи не собираются ставитьс очень тяжелой авторизацией.

Я думаю, что самая простая система для создания - это цифровая подпись файла лицензии, который содержит информацию о продукте, пользователе и его продолжительности.

Это означает, что любаяизменение файла лицензии делает цифровую подпись недействительной.

ДиЖитальная подпись может быть получена из класса DSACryptoServiceProvider с использованием метода SignData.

Для подписи данных требуется закрытый ключ, а открытая часть этого ключа может использоваться для проверки подписи: (таким образом, публичнаяключ должен быть доступен приложению)

DSAXCryptoServiceProvider имеет методы для создания и использования ключей:

DSACryptoServiceProvider.ToXMLString (bool includePrivate);

возвращает Public или Public & Public &Закрытые ключи в настоящее время в поставщике услуг представлены в виде строки XML.

DSACryptoServiceProvider.FromXMLString (String xmlString)

Этот метод устанавливает новый DSACryptoServiceProvider с существующими частными или открытыми ключами, полученными из DSACryptoServiceProvider.ToXString ()

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

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

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

У меня есть пример системы, которую я написал, но она слишком велика, чтобы ее полностью цитировать, но это метод CreateLicense из нее:

    /// <summary>
    /// use a private key to generate a secure license file. the private key must match the public key accessible to
    /// the system validating the license.
    /// </summary>
    /// <param name="start">applicable start date for the license file.</param>
    /// <param name="end">applicable end date for the license file</param>
    /// <param name="productName">applicable product name</param>
    /// <param name="userName">user-name</param>
    /// <param name="privateKey">the private key (in XML form)</param>
    /// <returns>secure, public license, validated with the public part of the key</returns>
    public static License CreateLicense(DateTime start, DateTime end, String productName, String userName, String privateKey)
    {
        // create the licence terms:
        LicenseTerms terms = new LicenseTerms()
        {
            StartDate = start,
            EndDate = end,
            ProductName = productName,
            UserName = userName
        };

        // create the crypto-service provider:
        DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();

        // setup the dsa from the private key:
        dsa.FromXmlString(privateKey);

        // get the byte-array of the licence terms:
        byte[] license = terms.GetLicenseData();

        // get the signature:
        byte[] signature = dsa.SignData(license);

        // now create the license object:
        return new License()
        {
            LicenseTerms = Convert.ToBase64String(license),
            Signature = Convert.ToBase64String(signature)
        };
    }

Метод проверки:

    /// <summary>
    /// validate license file and return the license terms.
    /// </summary>
    /// <param name="license"></param>
    /// <param name="publicKey"></param>
    /// <returns></returns>
    internal static LicenseTerms GetValidTerms(License license, String publicKey)
    {
        // create the crypto-service provider:
        DSACryptoServiceProvider dsa = new DSACryptoServiceProvider();

        // setup the provider from the public key:
        dsa.FromXmlString(publicKey);

        // get the license terms data:
        byte[] terms = Convert.FromBase64String(license.LicenseTerms);

        // get the signature data:
        byte[] signature = Convert.FromBase64String(license.Signature);

        // verify that the license-terms match the signature data
        if (dsa.VerifyData(terms, signature))
            return LicenseTerms.FromString(license.LicenseTerms);
        else
            throw new SecurityException("Signature Not Verified!");
    }

Условия лицензии Class:

    /// <summary>
    /// terms of the license agreement: it's not encrypted (but is obscured)
    /// </summary>
    [Serializable]
    internal class LicenseTerms
    {
        /// <summary>
        /// start date of the license agreement.
        /// </summary>
        public DateTime StartDate { get; set; }

        /// <summary>
        /// registered user name for the license agreement.
        /// </summary>
        public String UserName { get; set; }

        /// <summary>
        /// the assembly name of the product that is licensed.
        /// </summary>
        public String ProductName { get; set; }

        /// <summary>
        /// the last date on which the software can be used on this license.
        /// </summary>
        public DateTime EndDate { get; set; }

        /// <summary>
        /// returns the license terms as an obscure (not human readable) string.
        /// </summary>
        /// <returns></returns>
        public String GetLicenseString()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // create a binary formatter:
                BinaryFormatter bnfmt = new BinaryFormatter();

                // serialize the data to the memory-steam;
                bnfmt.Serialize(ms, this);

                // return a base64 string representation of the binary data:
                return Convert.ToBase64String(ms.GetBuffer());

            }
        }

        /// <summary>
        /// returns a binary representation of the license terms.
        /// </summary>
        /// <returns></returns>
        public byte[] GetLicenseData()
        {
            using (MemoryStream ms = new MemoryStream())
            {
                // create a binary formatter:
                BinaryFormatter bnfmt = new BinaryFormatter();

                // serialize the data to the memory-steam;
                bnfmt.Serialize(ms, this);

                // return a base64 string representation of the binary data:
                return ms.GetBuffer();

            }
        }

        /// <summary>
        /// create a new license-terms object from a string-representation of the binary
        /// serialization of the licence-terms.
        /// </summary>
        /// <param name="licenseTerms"></param>
        /// <returns></returns>
        internal static LicenseTerms FromString(String licenseTerms)
        {

            using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(licenseTerms)))
            {
                // create a binary formatter:
                BinaryFormatter bnfmt = new BinaryFormatter();

                // serialize the data to the memory-steam;
                object value = bnfmt.Deserialize(ms);

                if (value is LicenseTerms)
                    return (LicenseTerms)value;
                else
                    throw new ApplicationException("Invalid Type!");

            }
        }

    }
10 голосов
/ 02 сентября 2010

Существует множество систем управления лицензиями для .NET (есть даже одна встроенная для контроля лицензирования ).Быстрый поиск Google для ".NET License Manager" привел к появлению бесплатной системы Open License .

Я думаю, вы можете легко найти больше.

1 голос
/ 03 февраля 2019

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

У меня лучший опыт работы с Библиотека лицензирования Treek . Это дешево даже для одного разработчика, безопасно и с хорошей поддержкой. При сравнении затрат TLL дешевле аренды собственного разработчика для выполнения той же работы.

Кроме того, вам нужно будет защитить свои источники. Для этого мы используем EAZ Fuscator , но есть и бесплатные варианты. EAZ очень хороший, но очень дорогой.

0 голосов
/ 02 сентября 2010

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

Интересная статья о защите программного обеспечения (игр) может бытьнайдено здесь: http://www.positech.co.uk/talkingtopirates.html

0 голосов
/ 02 сентября 2010

Один из подходов - создать собственную систему частичного подтверждения ключа В Code Project доступна версия VB.NET:

http://www.codeproject.com/KB/security/cdkeys.aspx

...