C#桌面应用程序的许可证
如何在C#桌面应用程序中添加许可证? 我需要找到一个合适的免费方法来防止未经授权的用户安装我的软件。
.NET有很多许可证管理系统(甚至还有一个用于许可控制的内置系统 )。 一个快速谷歌围绕“.NET许可证管理器”推出了免费的开放许可证系统。
我希望你能轻松找到更多。
我可能有点迟了,但我花了一些时间试图找到一种快速有效的方法来保护一个小的C#应用程序,我想分享我的结果。
您似乎可以轻松地使用RSA构建自己的,相当安全的许可系统。
显然,在保护软件方面没有任何防弹措施(这就像保护你的房子免受窃贼:警报,吠叫狗和栅栏使它比它的价值更麻烦,但它们不会阻止某人决定进入)
因此,让它比它的价值更麻烦是软件保护中的关键词:如果你提供一个价值1,000,000美元的ERP系统,你会想要通过网络服务获得非常好的保护(以及用户为系统支付这么多费用)允许该系统持续上网不会有问题)
但是,如果您只为一个小应用程序收取5至30美元的费用,用户将不会忍受非常严厉的授权。
我认为最简单的系统是对包含产品,用户及其持续时间细节的许可证文件进行数字签名。
这意味着对许可证文件的任何修改都会使数字签名无效。
可以使用SignData方法从DSACryptoServiceProvider类获取数字签名。
需要私钥来对数据进行签名,并且该密钥的公共部分可用于validation签名:(因此应用程序必须可以访问公钥)
DSAXCryptoServiceProvider具有创建和使用键的方法:
DSACryptoServiceProvider.ToXMLString(bool includePrivate);
返回当前在服务提供程序中的公钥或公钥和私钥作为XML字符串。
DSACryptoServiceProvider.FromXMLString(String xmlString)
此方法设置一个新的DSACryptoServiceProvider,其中包含从DSACryptoServiceProvider.ToXMLString()获取的现有私钥或公钥
该系统安全性的唯一缺陷是用户可能破坏提供他们自己的公钥。 这将允许他们从他们自己的私钥生成他们自己的许可文件。
这可以通过另外为应用程序签署所需资源(例如包含应用程序的基本逻辑的.dll,甚至是.exe本身)来获得 – 因此,如果更改了公钥,则此附加(隐藏)签名将失效。
其他改进方法包括隐藏许可条款(使用二进制格式化程序将包含许可条款的数据结构序列化为字节数组,然后使用Convert.ToBase64String()将非常有效地模糊许可条款,即使用户能够替换他们仍需要计算数据表示的公钥
我有一个我编写的示例系统,但它太大了,不能完全引用,但这是它的CreateLicense方法:
/// /// 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. /// /// applicable start date for the license file. /// applicable end date for the license file /// applicable product name /// user-name /// the private key (in XML form) /// secure, public license, validated with the public part of the key 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) }; }
validation方法:
/// /// validate license file and return the license terms. /// /// /// /// 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!"); }
许可条款类:
/// /// terms of the license agreement: it's not encrypted (but is obscured) /// [Serializable] internal class LicenseTerms { /// /// start date of the license agreement. /// public DateTime StartDate { get; set; } /// /// registered user name for the license agreement. /// public String UserName { get; set; } /// /// the assembly name of the product that is licensed. /// public String ProductName { get; set; } /// /// the last date on which the software can be used on this license. /// public DateTime EndDate { get; set; } /// /// returns the license terms as an obscure (not human readable) string. /// /// 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()); } } /// /// returns a binary representation of the license terms. /// /// 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(); } } /// /// create a new license-terms object from a string-representation of the binary /// serialization of the licence-terms. /// /// /// 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!"); } } }
我们使用Eziriz .NET Reactor对我们的商业软件进行模糊处理和许可。 它非常好,而且价格也不贵。
(我与eziriz没有任何关系,我只是一个满意的客户)
编辑:抱歉,看到“免费”这个词太晚了
一种方法是推出自己的部分密钥validation系统 。 Code Project上有一个VB.NET版本:
警惕您为保护应用程序付出了多少努力; 如果非常强大(如每次运行时必须输入密码),如果它很容易被打破或关闭,可能会浪费时间。
有关软件保护(游戏)的有趣文章可以在这里找到: http : //www.positech.co.uk/talkingtopirates.html