最近做的几个项目都用到了软件加密问题,使用加密狗控制软件使用和安装就会碰到一个问题:就是如何识别客户端电脑的唯一性?
网上查了一下,有这么几种解决方案:
1、通过硬盘出厂编号;
(缺点是:有的牌子的硬盘,比如三星,没有出厂编号,或读不到。还有,如何得到出厂编号,也是鄙人想求教各位的。)
2、网卡MAC地址;
(缺点是:可以做虚拟网卡,或者直接修改网卡MAC值。)
3、硬盘序列号(Valume Serial Number);
(这个,缺点就多了,一是格式化后该序列号就变了;二是可以用软件修改;三是可以克隆出相同的序列号。)
4、主板编号;
(缺点,也是有的牌子,其编号读不到,另外好象相同批次的主板,编号也相同。如何读到,也是我想求教的。)
5、BIOS编号;
(缺点,好象也是相同批次的产品,编号也相同。如何取得该编号,也是想求教的。)
6、CPU编号;
(缺点,也是有的牌子,比如AMD,没有编号,或者获取不到。如何取得该编号,也是想求教的。)
可以看出,以上几种方式都没有能很好的解决此问题,因此我考虑将几个方式组合使用,这样加密狗在匹配验证的时候准确率可能会更高一些。
具体做法是,在用户安装软件的过程中需要插入加密狗验证管理员分配的用户名和密码,验证通过后继续安装同时读取客户端机器的以上信息(包括
硬盘出厂编号,
网卡MAC地址,
硬盘序列号,
主板编号,
BIOS编号
,
CPU编号
)并写入加密狗存储以备将来做客户合法性验证使用。
在客户使用软件过程中,首先要插入加密狗进行合法性验证,此时将重新读取客户端机器上相关信息和加密狗中记录的相应信息一一匹配,但不要求全部匹配成功,只要匹配成功2到3项以上即可认为验证通过。因为这些信息中部分是在有些电脑上获取不到或被修改,再或者同一批次相同的情况,所以不可能完全匹配。当然这些信息也不可能全部都被修改,所以这样验证的稳定性和准确度还是比较高的。目前也是没有更好办法的好办法了。
另外,还有一种做法是在安装期间自动生成一个GUID,并保存在
客户端机器上
比较隐蔽的位置同时写入加密狗记录下来,然后使用时将读取该机器码文件和加密狗相匹配,这样做成功率几乎是百分之百了,但是这样做有几个缺点:
1.文件容易被误删或损坏,即时隐藏也不保准。
2.如果客户知道该文件,复制到其他客户机器上也可以使用,失去了电脑唯一性的特点。
顺便附上获取相关硬件编号的代码,网上搜集的以供学习:
获取硬盘出厂编号:
public static string GetHardDiskID()
{ //Get the first Hard disk 14 bits ID var strHardDiskID = string.Empty;
try
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
var moc = searcher.Get();
foreach (var mo in moc)
{
strHardDiskID = mo["SerialNumber"].ToString().Trim();
break;
}
return strHardDiskID;
}
catch
{
return string.Empty;
}
}
获取硬盘出厂编号:
public static string GetHardDiskID2()
{
var strHardDiskID = string.Empty;
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher();
//signature 需要程序以管理员身份运行
try
{
wmiSearcher.Query = new SelectQuery("Win32_DiskDrive", "", new string[] { "PNPDeviceID", "signature" });
ManagementObjectCollection myCollection = wmiSearcher.Get(); ManagementObjectCollection.ManagementObjectEnumerator em = myCollection.GetEnumerator(); myCollection.GetEnumerator();
em.MoveNext();
ManagementBaseObject mo = em.Current; strHardDiskID = mo.Properties["signature"].Value.ToString().Trim();
return strHardDiskID;
}
catch
{
return string.Empty;
}
}
获取CPU的ID:
public static string GetCpuID()
{
//Get the first CPU 16 bits ID var strCpuID = string.Empty;
try
{
var mc = new ManagementClass("Win32_Processor");
var moc = mc.GetInstances();
foreach (var mo in moc)
{
strCpuID = mo.Properties["ProcessorId"].Value.ToString();
break;
}
return strCpuID;
}
catch
{
return string.Empty;
}
}
获取Mac地址:
public static string GetMacAddress()
{
var mac = string.Empty;
try
{
var mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
var moc = mc.GetInstances();
foreach (var mo in moc)
{
if ((bool)mo["IPEnabled"] == true)
{
mac