由于要求软件加密,并且有使用时间限制,同时要防止拷贝到其他电脑使用,我们需要考虑以下几点:
唯一标识机器:为了确保软件只能在授权的机器上运行,我们需要一个能够唯一标识计算机的硬件信息。通常可以使用CPU序列号、硬盘序列号、MAC地址等。但需要注意的是,有些硬件可能没有序列号或者用户可能更换硬件,所以需要权衡。
时间记录:我们需要记录软件第一次安装使用的时间,然后计算累计使用时间。这里要注意,即使用户修改系统时间,我们也要有一定的防范措施。
注册机制:当软件使用超过三个月后,需要注册才能恢复使用。注册机制可以是通过获取机器码,然后由授权方生成注册码,输入注册码后重置使用时间。
数据存储:我们需要将关键数据(如首次使用时间、累计使用时间、注册信息等)存储在安全的地方,防止用户轻易修改。可以考虑使用加密文件、注册表等。
防止拷贝:通过绑定机器硬件信息,确保软件只能在特定的机器上运行。
设计思路
获取机器唯一标识:
我们可以结合CPU序列号和主板序列号来生成机器码。如果无法获取,再考虑其他硬件信息。
记录使用时间:
在软件第一次运行时,记录当前时间(作为安装时间)并存储。
每次启动软件时,检查当前时间与安装时间的差值,累计使用时间超过三个月则停止使用。
注册机制:
用户将机器码发送给授权方,授权方根据机器码生成注册码。
软件验证注册码,如果正确,则重置使用时间(再延长三个月)。
存储数据:
我们将安装时间、累计使用时间、注册信息等存储在一个加密的文件中,或者使用注册表。为了简单,我们使用文件,并加密存储。
防止修改系统时间:
我们可以记录每次运行的时间,并检查当前时间是否比上次运行时间早(系统时间被调回),如果调回则给出警告或停止运行。
代码实现步骤
生成机器码:
使用ManagementObjectSearcher获取CPU和主板的序列号,然后组合生成一个字符串,并计算其哈希值作为机器码。
记录首次运行时间:
如果首次运行,则记录当前时间,并存储到加密文件中。
检查使用时间:
读取存储的首次运行时间,计算与当前时间的差值,如果超过三个月(例如90天),则提示注册。
注册功能:
输入注册码,验证注册码是否正确(注册码可以根据机器码和某种算法生成,例如使用RSA或AES加密,这里为了简单,可以使用对称加密或哈希加盐)。
如果注册码正确,则重置首次运行时间为当前时间,并更新存储。
加密存储:
使用AES或DES加密存储关键数据(首次运行时间、机器码等)。
csharp
public class ProtectionManager
{
public string registryPath { get; set; } = @"SOFTWARE\YourCompany\YourApp";
private string dataFile = "license.dat";
private int trialDays = 90; // 三个月试用期
public bool CheckAuthorization()
{
// 1. 检查机器绑定
if (!CheckMachineBinding())
return false;
// 2. 检查使用时间
if (!CheckUsageTime())
return false;
return true;
}
private bool CheckMachineBinding()
{
var currentMachineId = GetMachineFingerprint();
var storedMachineId = ReadMachineId();
// 首次运行,保存机器ID
if (string.IsNullOrEmpty(storedMachineId))
{
return SaveMachineId(currentMachineId);
}
// 检查是否在同一台机器上
return currentMachineId == storedMachineId;
}
private bool CheckUsageTime()
{
var installDate = GetInstallDate();
var usageDays = (DateTime.Now - installDate).TotalDays;
if (usageDays > trialDays)
{
// 试用期已过,检查是否已注册
if (!IsRegistered())
{
MessageBox.Show($"试用期已结束!请注册后继续使用。",
"试用期结束",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return false;
}
else
{
// 已注册,检查注册有效期
return CheckRegistrationValidity();
}
}
return true;
}
private string GetMachineFingerprint()
{
var components = new List<string>();
try
{
// CPU ID
using (var searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor"))
{
foreach (ManagementObject obj in searcher.Get())
{
components.Add(obj["ProcessorId"]?.ToString() ?? "");
break;
}
}
// 主板序列号
using (var searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard"))
{
foreach (ManagementObject obj in searcher.Get())
{
components.Add(obj["SerialNumber"]?.ToString() ?? "");
break;
}
}
// 硬盘序列号
using (var searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_PhysicalMedia"))
{
foreach (ManagementObject obj in searcher.Get())
{
components.Add(obj["SerialNumber"]?.ToString() ?? "");
break;
}
}
}
catch
{
// 如果获取硬件信息失败,使用备用方案
components.Add(Environment.MachineName);
components.Add(Environment.UserName);
}
var combined = string.Join("|", components);
return ComputeHash(combined);
}
private string ComputeHash(string input)
{
using (var sha256 = SHA256.Create())
{
var bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
return Convert.ToBase64String(bytes);
}
}
private bool SaveMachineId(string machineId)
{
try
{
using (var key = Registry.CurrentUser.CreateSubKey(registryPath))
{
key.SetValue("MachineId", EncryptString(machineId));
key.SetValue("InstallDate", EncryptString(DateTime.Now.ToString("yyyy-MM-dd")));
}
return true;
}
catch
{
return false;
}
}
private string ReadMachineId()
{
try
{
using (var key = Registry.CurrentUser.OpenSubKey(registryPath))
{
if (key?.GetValue("MachineId") is string encryptedId)
return DecryptString(encryptedId);
}
}
catch { }
return null;
}
private DateTime GetInstallDate()
{
try
{
using (var key = Registry.CurrentUser.OpenSubKey(registryPath))
{
if (key?.GetValue("InstallDate") is string encryptedDate)
{
var dateStr = DecryptString(encryptedDate);
if (DateTime.TryParse(dateStr, out var date))
return date;
}
}
}
catch { }
return DateTime.Now;
}
public bool RegisterSoftware(string licenseKey)
{
if (ValidateLicenseKey(licenseKey))
{
try
{
using (var key = Registry.CurrentUser.CreateSubKey(registryPath))
{
key.SetValue("LicenseKey", EncryptString(licenseKey));
key.SetValue("RegisterDate", EncryptString(DateTime.Now.ToString("yyyy-MM-dd")));
key.SetValue("IsRegistered", "1");
}
// 重置试用期
ResetTrialPeriod();
return true;
}
catch
{
return false;
}
}
return false;
}
private bool ValidateLicenseKey(string licenseKey)
{
// 这里实现您的许可证验证逻辑
// 可以是在线验证、离线文件验证等
// 示例:简单的格式验证
if (string.IsNullOrEmpty(licenseKey) || licenseKey.Length != 25)
return false;
// 实际应用中应该使用更复杂的验证,比如:
// 1. 连接到许可证服务器验证
// 2. 验证数字签名
// 3. 检查许可证是否被撤销等
return true;
}
private bool IsRegistered()
{
try
{
using (var key = Registry.CurrentUser.OpenSubKey(registryPath))
{
return key?.GetValue("IsRegistered") != null;
}
}
catch
{
return false;
}
}
private bool CheckRegistrationValidity()
{
// 检查注册是否有效
// 这里可以添加更复杂的注册验证逻辑
return IsRegistered();
}
private void ResetTrialPeriod()
{
try
{
using (var key = Registry.CurrentUser.CreateSubKey(registryPath))
{
key.SetValue("InstallDate", EncryptString(DateTime.Now.ToString("yyyy-MM-dd")));
}
}
catch { }
}
public int GetRemainingDays()
{
var installDate = GetInstallDate();
var usageDays = (DateTime.Now - installDate).TotalDays;
var remaining = trialDays - (int)usageDays;
return Math.Max(0, remaining);
}
// 简单的加密解密方法
private string EncryptString(string plainText)
{
try
{
var bytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(bytes);
}
catch
{
return plainText;
}
}
private string DecryptString(string encryptedText)
{
try
{
var bytes = Convert.FromBase64String(encryptedText);
return Encoding.UTF8.GetString(bytes);
}
catch
{
return encryptedText;
}
}
}
使用软件时检测
csharp
public partial class Form1 : Form
{
private ProtectionManager protection;
public Form1()
{
InitializeComponent();
protection = new ProtectionManager();
// 检查软件授权状态
if (!protection.CheckAuthorization())
{
MessageBox.Show("软件授权验证失败!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
return;
}
InitializeUI();
}
private void InitializeUI()
{
var remainingDays = protection.GetRemainingDays();
lblStatus.Text = $"授权状态:正常,剩余天数:{remainingDays}";
}
}
注册软件
csharp
public partial class RegisterForm : Form
{
private ProtectionManager protection;
public RegisterForm(ProtectionManager protectionManager)
{
InitializeComponent();
protection = protectionManager;
}
private void btnRegister_Click(object sender, EventArgs e)
{
var licenseKey = txtLicenseKey.Text.Trim();
if (protection.RegisterSoftware(licenseKey))
{
MessageBox.Show("注册成功!软件已激活三个月使用权。", "注册成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
Close();
}
else
{
MessageBox.Show("注册失败!请输入有效的许可证密钥。", "注册失败",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}