- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
如何向我的 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/
这显然有可能导致一场激烈的 war ,但无论如何,我试一试……(目前)还没有任何明确的答案。 在我的一台机器上,我确实被切换/升级到 Matlab 2012b。这是一个漂亮的新桌面,好吧。但出于很多原
当我的 Docker 容器启动时,我收到以下通知: Docker Desktop has detected that you shared a Windows file into a WSL 2 co
我希望能够(从服务器)连接到远程 PC 并能够访问其文件。我正在尝试使用 PHP 或 JavaScript 来完成此操作。 所以我想知道 1) 是否可能以及 2) 如何做到。 有人有任何示例/解决方案
我想使用 DirectX 为 Windows 7 制作动画桌面背景。我正在使用 C#、SlimDX 和几个 Windows API 函数的 P/Invoke 导入。我对 native Windows
是否可以为 Mac 开发动态桌面?我所说的“动态”是指其图像采用系统参数(例如时间和作业信息)并使用此信息来更新图像的桌面。有关图像状态的信息也将在 session 之间保留。我不是在谈论电影或随机但
我正在 LibGDX 中构建一个仅限桌面的应用程序。该游戏内置了一个 map 编辑器,您可以切换到并更改游戏 map 。我想添加一个功能,如果用户单击关闭窗口并且有未保存的编辑,它会提示您是否要在关闭
有没有像样的Windows桌面JSON lines (JSONL)格式查看器? 这种格式也称为: 行分隔的 JSON (LDJSON) 换行符分隔的 JSON (NDJSON) 我正在寻找至少能够从
我有一个UITableView,它在单元格中显示大量图像,并且我对滚动性能并不满意。我的 UITableView 类似于 iPhone 上的照片应用程序。有谁知道为什么 iphone 照片应用程序滚动
let img1 = document.createElement('img'); img1.setAttribute('src', 'https://caniuse.com/img/browsers
我在同一窗体上有两个不同的网格控件。它们共享相同的上下文菜单。当我选择上下文菜单项时,我无法确定哪个控件是所有者。 最佳答案 ContextMenuStrip 类的 SourceControl 属性将
我已经安装了 Docker Desktop ( version : 2.3.0.4 ) 并启用了 Kubernetes . 我部署了几个 PODS,一切正常,从昨天开始,我遇到了下面提到的一个奇怪的问
我正在制作需要实现TableView的应用程序。 我想将背景图像应用到桌面 View 。 谁能帮我解决这个问题。我正在使用下面的代码来创建 TableView Titanium.UI.setBackg
我在同一窗体上有两个不同的网格控件。它们共享相同的上下文菜单。当我选择上下文菜单项时,我无法确定哪个控件是所有者。 最佳答案 ContextMenuStrip 类的 SourceControl 属性将
您能建议一些库在我的桌面 Java 应用程序中创建雷达图吗? 谢谢 最佳答案 似乎JFreeChart提供了SpiderWebPlot 。 images for which看起来像雷达图。 关于jav
这个问题已经有答案了: 已关闭10 年前。 Possible Duplicate: Not possible to launch a file on a network using Java Desk
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
我想知道是否可以(使用JAVA)识别用于发出请求的计算机类型,例如:服务器、台式机、PDA(平板电脑、手机等)? 谢谢! 最佳答案 取决于您使用什么来接受请求。对于 http 请求,信息位于请求 he
我添加了一个事件处理程序,用于滚动到我的桌面 View ,但它仅在我使用滚轮滚动时才起作用,但我也需要它在您单击并拖动滚动条时起作用。任何想法有什么问题吗?我尝试使用不同的方法来处理该事件,但没有一个
我想开始开发桌面 Java 应用程序,并且我想知道 Java 社区使用什么。 我从 Swing 开始,但发现它非常初级。 我习惯于在 Visual Studio 2010 中使用 .net c# WP
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我是一名优秀的程序员,十分优秀!