加密狗授权方式介绍

每只加密狗都有一个固定的序列号,并且一般是无法修改的。软件运行时读取加密狗的序列号进行判断,序列号通过验证后才能正常使用软件。

选购一套加密狗开发套件

我选购了SaftNet的USB软件狗,入手后查阅开发资料(不同品牌的加密狗开发资料一般都不同),整理需要用到的开发资源如下:

  • SoftDogSetup.dll:提供加密狗驱动相关操作的DLL

需要用到以下方法:

(1)获取狗驱动程序安装信息接口函数GetDogDriverInfo,定义如下:

int PASCAL GetDogDriverInfo();

参数:无

返回值:

0 没有安装驱动程序

1 驱动版本相同(并口和usb)

2 USB驱动版本相同

3 并口驱动版本相同

4 已安装旧版本驱动 (并口和usb)

5 已安装旧版本USB驱动

6 已安装旧版本并口驱动

7 已安装新版本驱动 (并口和usb)

8 已安装新版本USB驱动

9 已安装新版本并口驱动

3008 没有管理员权限

(2)驱动安装的函数接口InstDriver,定义如下:

Int PASCAL InstDriver(int iFlag);

参数:

iFlag = 1 只安装USB狗驱动

iFlag = 2 只安装并口狗驱动

iFlag = 3 安装并口狗驱动和USB狗驱动

返回值:

如果运行成功则返回0,否则返回错误值。

(3)驱动卸载的函数接口UninstallDriver,定义如下:

int PASCAL UninstallDriver(int iFlag);

参数:

iFlag = 1 只卸载USB狗驱动

iFlag = 2 只卸载并口狗驱动

iFlag = 3 卸载并口狗驱动和USB狗驱动

返回值:

如果运行成功则返回0,否则返回错误值。

  • win32dll.dll:提供加密狗读写操作的DLL

需要用到以下方法:

(1)DWORD WINAPI DogRead (DWORD dwBytes,DWORD dwAddr,char *pData);

函数返回0表示读写成功,其它返回值为错误代码。

变量说明:

DWORD dwBytes:每次变换或读写操作的字节数

DWORD dwAddr:每次读写操作时狗中的首地址

char * pData :指向变换操作缓冲区的数据指针

实现加密狗授权(C#)

定义SoftDog类

首先定义一个SoftDog的静态类,静态类的主要特点如下:

  • 它们仅包含静态成员。
  • 它们不能被实例化。
  • 它们是密封的,不可被继承。
  • 它们不能包含实例构造函数。
using System; 
using System.Runtime.InteropServices; 
namespace HCommon.License 
{ 
StructLayout(LayoutKind.Sequential)] 
public static class SoftDog 
    { 
    } 
}

然后,使用DllImport引入使用到的dll方法,因为参数和返回值都很不友好,所以定义为private,不直接向外部公开。

///<summary> 
/// 获取狗驱动程序安装信息接口函数GetDogDriverInfo 
///</summary> 
[DllImport("SoftDogSetup.dll", CharSet = CharSet.Ansi)] 
private static extern ushort GetDogDriverInfo(); 
///<summary> 
/// 驱动安装的函数接口InstDriver 
///</summary> 
[DllImport("SoftDogSetup.dll", CharSet = CharSet.Ansi)] 
private static extern ushort InstDriver(ushort flag); 
///<summary> 
/// 驱动卸载的函数接口UninstallDriver 
///</summary> 
[DllImport("SoftDogSetup.dll", CharSet = CharSet.Ansi)] 
private static extern ushort UninstallDriver(ushort flag); 
///<summary> 
/// 读取加密狗单函数接口DogRead 
///</summary> 
[DllImport("win32dll.dll", CharSet = CharSet.Ansi)] 
private static extern uint DogRead(uint length, uint startIndex, byte[] data);

然后,定义加密狗驱动相关的public方法

public static bool DriverInstalled 
{ 
get 
    { 
ushort code = GetDogDriverInfo(); 
if (code == 3008) throw new HCommon.HException("{0}:没有管理员权限!", 3008); 
if (code == 1 || code == 2 || code == 7 || code == 8) return true; 
return false; 
    } 
} 
public static void InstallDriver() 
{ 
ushort code = GetDogDriverInfo(); 
if (code == 3008) throw new HCommon.HException("{0}:没有管理员权限!", 3008); 
if (code == 1 || code == 2 || code == 7 || code == 8) return; 
if (code == 4 || code == 5) 
        UninstallDriver(); 
    code = InstDriver(1); 
if (code != 0) throw new HCommon.HException("{0}:安装驱动失败!", code); 
} 
public static void UninstallDriver() 
{ 
ushort code = UninstallDriver(1); 
if (code != 0) throw new HCommon.HException("{0}:卸载驱动失败!", code); 
}

最后,定义读取加密狗序列号的public方法

public static string SerialNumber 
{ 
get 
    { 
uint code = 0; 
byte[] data = new byte[100]; 
        code = DogRead(0, 0, data); 
if (code != 0) 
        { 
throw new HCommon.HException("{0}:读取序列号失败!", code); 
        } 
uint sn = BitConverter.ToUInt32(data, 0); 
return sn.ToString(); 
    } 
}

使用SoftDog类

使用SoftDog的客户程序代码片段:

…
//软件启动时先判断是否安装加密狗驱动 
if (!SoftDog.DriverInstalled) 
{ 
SoftDog.InstallDriver(); 
MessageBox.Show("已安装加密狗驱动,请插入加密狗。"); 
} 
…
//定义序列号属性 
private static readonly string g_Key = "12345678";
private string SerialNumber 
{ 
get 
    { 
try 
        { 
string sn = SoftDog.SerialNumber; 
if (string.IsNullOrEmpty(sn)) return string.Empty; 
return sn; 
        } 
catch (Exception ex) 
        { 
ApplicationLog.LogException(ex); 
        } 
return string.Empty; 
    } 
} 
//序列号判断的方法 
private void CheckLicense() 
{ 
if (SerialNumber != g_Key) 
    { 
MessageBox.Show("对不起,计算机必须插入正确的加密狗,软件才能授权使用,请按确定退出系统。"); 
Application.Exit(); 
    } 
} 
…

另外,软件运行时也应该定期地检查序列号,当发现加密狗已被拔出时终止软件的使用。需要定义一个Timer,每隔2分钟调用一次CheckLicense方法即可。

几种常用授权方式总结

  • 软件序列号授权:支持单机,序列号容易泄漏。
  • 软件序列号网络注册激活:授权控制最理想,但不支持单机。
  • 加密狗授权:支持单机,效果比软件序列号授权好,但占用一个硬件端口。