gpt4 book ai didi

c# - C# 桌面应用程序许可证

转载 作者:IT王子 更新时间:2023-10-29 04:12:08 26 4
gpt4 key购买 nike

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

最佳答案

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

看来您可以相当轻松地使用 RSA 构建您自己的、相当安全的许可系统。

显然,在保护软件方面没有什么是防弹的(这就像保护您的房子免遭窃贼:警报、狂吠的狗和栅栏使它变得比它的值(value)更麻烦,但它们不会阻止决心进入的人)

因此,软件保护中的关键词是让麻烦大于值(value):如果您提供 1,000,000 美元的 E.R.P.系统,您会希望拥有通过网络服务授权的非常好的保护(并且为系统支付那么多费用的用户不会有允许该系统持续访问互联网的问题)

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

我认为最简单的系统是对包含产品详细信息、用户及其持续时间的许可文件进行数字签名。

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

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

需要私钥来签署数据,并且该 key 的公共(public)部分可用于验证签名:(因此应用程序必须可以访问公钥)

DSAXCryptoServiceProvider 具有创建和使用 key 的方法:

DSACryptoServiceProvider.ToXMLString(bool includePrivate);

以 XML 字符串的形式返回服务提供者中当前的公钥或公钥和私钥。

DSACryptoServiceProvider.FromXMLString(String 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!");

}
}

}

关于c# - C# 桌面应用程序许可证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3624149/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com