web-dev-qa-db-fra.com

Licence pour l'application de bureau C #

Comment puis-je ajouter une licence à mon application de bureau C #? Je dois trouver une méthode gratuite appropriée pour empêcher les utilisateurs non autorisés d’installer mon logiciel.

26
Noro

Il existe de nombreux systèmes de gestion de licences pour .NET (il existe même un intégré pour les contrôles de licence ). Un rapide Google pour "gestionnaire de licences .NET" a lancé le Open License system, qui est gratuit.

Je pense que vous pouvez facilement trouver plus.

10
Dr Herbie

Je suis probablement un peu en retard, mais j'ai passé un peu de temps à essayer de trouver une méthode rapide et efficace pour sécuriser une petite application C #, et j'aimerais partager mes résultats.

Il semble que vous puissiez construire votre propre système de licences relativement sécurisé en utilisant RSA de manière relativement simple. 

Évidemment, rien n’est à l’abri en matière de protection des logiciels (c’est comme protéger votre maison des cambrioleurs: alarmes, aboiements de chiens et barrières rendent la tâche plus ardue qu’elle ne vaut la peine, mais ils n’empêcheront pas une personne déterminée d’y entrer)

La phrase clé de la protection logicielle est donc de faire en sorte que le problème soit plus grave que jamais: si vous offrez 1 000 000 $ E.R.P. système, vous voudriez disposer d’une protection vraiment efficace, autorisée par un service Web (et les utilisateurs qui paient autant pour un système n’auraient aucun problème à autoriser ce système à un accès Internet permanent)

Toutefois, si vous ne facturez que 5 à 30 dollars pour une petite application, les utilisateurs ne toléreront pas une autorisation très lourde.

Je pense que le système le plus simple à produire consiste à signer numériquement un fichier de licence contenant les détails du produit, de l'utilisateur et de sa durée.

Cela signifie que toute modification du fichier de licence rend la signature numérique invalide.

La signature numérique peut être obtenue à partir de la classe DSACryptoServiceProvider, à l'aide de la méthode SignData.

Une clé privée est nécessaire pour signer les données, et la partie publique de cette clé peut être utilisée pour valider la signature: (ainsi, la clé publique doit être accessible par l'application)

DSAXCryptoServiceProvider possède des méthodes pour créer et utiliser des clés:

DSACryptoServiceProvider.ToXMLString (bool includePrivate);

renvoie les clés publiques ou publiques et privées présentes dans le fournisseur de services sous forme de chaîne XML.

DSACryptoServiceProvider.FromXMLString (String xmlString)

Cette méthode configure un nouveau DSACryptoServiceProvider avec des clés privées ou publiques existantes obtenues à partir de DSACryptoServiceProvider.ToXMLString ().

La seule faille dans la sécurité de ce système serait la possibilité pour un utilisateur d'introduire une clé publique. Cela leur permettrait de générer leurs propres fichiers de licence à partir de leur propre clé privée.

Pour ce faire, vous pouvez également signer une ressource requise pour l'application (comme un fichier .dll contenant la logique essentielle de l'application, voire le fichier .exe lui-même). Ainsi, si la clé publique est modifiée, cette signature (masquée) supplémentaire devenir invalide.

D'autres moyens pour améliorer ceci incluent l'obscurcissement des termes de la licence (sérialiser une structure de données contenant les termes de la licence en utilisant le formateur binaire en un tableau d'octets, puis en utilisant Convert.ToBase64String () obscurcira assez efficacement les termes de la licence, et même si l'utilisateur a pu remplacer la clé publique dont il aurait encore besoin pour élaborer la représentation des données)

J'ai un exemple de système que j'ai écrit, mais il est trop gros pour être entièrement cité, mais voici la méthode 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)
        };
    }

Méthode Verify:

    /// <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!");
    }

Les termes de la licence

    /// <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!");

            }
        }

    }
53
Simon Bridge

Techniquement, il n’est pas facile de créer un système de licences fonctionnel et sécurisé. Si vous envisagez de développer un logiciel commercial, je vous conseillerais d’utiliser une solution commerciale. Les systèmes de licence codés sur mesure ont tendance à être vulnérables.

J'ai la meilleure expérience avec Bibliothèque de licences de Treek . Son bon marché même pour le développeur unique, son coffre-fort et avec un bon support. Lorsque vous comparez les coûts, TLL est moins cher que de louer votre propre développeur pour faire le même travail.

En outre, vous devrez protéger vos sources. Pour cela, nous utilisons EAZ Fuscator , mais des options gratuites sont également disponibles. EAZ est très bon, mais très cher.

0
panpernicek

Une approche consiste à lancer votre propre système de vérification de clé partielle . Il existe une version VB.NET disponible sur Code Project:

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

0
CtrlDot

Méfiez-vous des efforts que vous déployez pour protéger votre application. cela peut être du temps perdu s'il est facilement cassé ou offensant pour les utilisateurs s'il est très fort (par exemple, avoir à entrer un mot de passe à chaque exécution).

Un article intéressant sur la protection des logiciels (des jeux) est disponible ici: http://www.positech.co.uk/talkingtopirates.html

0
Tony