2010-09-02 146 views
22

如何向我的C#桌面应用程序添加许可证?我需要找到一种合适的免费方法来防止未经授权的用户安装我的软件。C#桌面应用程序许可证

+0

究竟你通过 “添加许可证” 是什么意思? – 2010-09-02 05:55:13

+0

应用程序必须具有用于安装的许可证密钥。 – Noro 2010-09-02 06:10:26

回答

9

有许多.NET的许可证管理系统(甚至有一个built-in for licensing controls)。一个快速谷歌周围的“.NET许可证管理器”扔了Open License系统,这是免费的。

我希望你可以轻松找到更多。

+2

开放许可证的URL已更改:https://sourceforge.net/projects/net-lic-mgr/ – 2015-02-02 19:56:34

0

警惕的你把多少精力在保护您的应用程序;如果它非常强大(例如,每次运行时都必须输入密码),它可能会被浪费时间。

的软件保护(游戏)有趣的文章可以在这里找到: http://www.positech.co.uk/talkingtopirates.html

1

我们使用 Eziriz .NET Reactor我们的商业软件的混淆和许可。这很不错,并不昂贵。

(我有eziriz没有隶属关系无论如何,我只是一个satified客户)

编辑:对不起,看到这个词“免费”为时已晚

50

我可能有点晚,但我花了一些时间试图找出一种快速有效的方法来保护一个小小的C#应用​​程序,并且我想分享我的结果。

您似乎可以合理轻松地使用RSA构建自己的,相当安全的许可证系统。显然,在保护软件方面没有什么是防弹的(就像保护你的房子免遭盗窃:警报,吠叫狗和栅栏使它比它的价值更麻烦,但它们不会阻止某些人决心获得in)

因此,让它比它值得的更麻烦是软件保护中的关键词:如果你要提供一个价值1,000,000美元的ERP系统,你会想要通过网络服务授权的真正好的保护(并且用户为系统支付多少费用并不会让系统持续上网成为问题)

但是,如果您只是收费一个小应用程序需要5- $ 30美元,用户不会忍受非常繁重的授权。

我认为制作最简单的系统是对包含产品细节,用户及其持续时间的许可证文件进行数字签名。

这意味着对许可证文件的任何修改都会导致数字签名无效。

数字签名可以使用SignData方法从DSACryptoServiceProvider类中获得。

私钥需要对数据进行签名,以及该密钥的公共部分可以用来验证签名:(因此公共密钥必须是由应用程序访问的)

的DSAXCryptoServiceProvider具有用于方法创建和使用密钥:

DSACryptoServiceProvider.ToXMLString(bool includePrivate);

返回Public或Public &当前在服务提供者中的私钥,作为XML字符串。

DSACryptoServiceProvider.FromXMLString(字符串的xmlString)

这种方法建立一个与现有)从DSACryptoServiceProvider.ToXMLString(获得的私有或公共密钥的新DSACryptoServiceProvider

在这个系统的安全唯一的缺陷是用户中断提供他们自己的公钥的可能性。这将允许他们从他们自己的私钥生成自己的许可证文件。

这可以通过额外签署应用程序所需的资源(如包含应用程序的基本逻辑的.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!"); 
    } 

许可条款类:

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

      } 
     } 

    } 
+0

伟大的东西。谢谢! – 2015-02-02 20:15:25

+0

真棒,tks ... – 2017-04-17 18:32:24

+0

我猜如果你争夺数据结构,就像给它看起来相关的完全不相关的属性,并从某些似乎无关的属性以某种方式计算相关属性,然后序列化和base64编码它,它应该是**真的很难弄清楚系统是如何工作的 – 2017-06-16 09:20:35