根据USB 序列号 生成USB Key
2008-09-18 18:13
232 查看
在软件安装的时候,常常要验证软件的有效性,这时候发行产品的时候会附带一个USB Key,主程序运行的时候检查这个Key的合法性,如果通过验证,那么启动主程序。
下面的代码提供了实现该方法的途径:/// <summary>
/// USB 操作相关
/// </summary>
public class UsbUtility
{
const string Key_File_Name = "Usb.key";
/// <summary>
/// 获取优盘唯一序列号,可能需要以管理员身份运行程序
/// </summary>
/// <returns></returns>
public static string GetUSBId()
{
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher("Select * From Win32_USBHub");
string id = "";
foreach (ManagementObject wmi_USB in wmiSearcher.Get())
{
string strPath = wmi_USB.Path.RelativePath;
string[] strArr = strPath.Split('/"');
string strTemp = strArr[1];
//VID_ 是真正的优盘标示
if (strTemp.StartsWith("USB////VID_"))
id += strTemp + ";";
}
return id.TrimEnd(';');
}
/// <summary>
/// 获取当前UsbKey,根据当前附加的序列号,生成 "序列号,UsbId"格式的字符串,并返回加密后的结果
/// 如果没有找到设备,那么返回空字符串
/// 如果返回值为空,请检查 message 的值。
/// </summary>
/// <param name="sourceNumber">要附加的序列号</param>
/// <param name="message">生成的操作信息</param>
/// <returns>当前加密后的UsbKey字符串</returns>
public static string GetCurrentUsbKey(string sourceNumber,out string message)
{
string strUsbId = GetUSBId();
if (strUsbId != "")
{
if (strUsbId.Split(';').Length == 1)
{
CheckCode cc = new CheckCode();
message = "OK";
string strTemp = sourceNumber+","+strUsbId ;
return cc.Encode(strTemp);
}
else
{
message = "当前有多个U盘,请拨除其它U盘。";
return "";
}
}
message = "未找到U盘或者U盘没有物理序列号。";
return "";
}
/// <summary>
/// 将一个新的UsbKey写到当前U盘上
/// </summary>
/// <param name="sourceNumber">U盘所在盘符</param>
/// <param name="sourceNumber">要附加的序列号</param>
/// <param name="message">生成的操作信息</param>
/// <returns></returns>
public static bool WriteUsbKeyFile(string driveName, string sourceNumber,out string message)
{
string strCurrentUsbKey = GetCurrentUsbKey(sourceNumber, out message);
if (strCurrentUsbKey != "")
{
if (driveName.EndsWith("//"))
driveName += "//";
string strCurrKeyFileName = driveName + Key_File_Name;
try
{
using (StreamWriter writer = File.CreateText(strCurrKeyFileName))
{
writer.Write(strCurrentUsbKey);
writer.Flush();
}
message = "OK";
return true;
}
catch (Exception ex)
{
message = ex.Message;
}
}
return false;
}
/// <summary>
/// 读取UsbKey文件的内容,返回内容格式为 "序列号,UsbId"格式的字符串
/// 如果未能正确读取文件,返回空字符。
/// </summary>
/// <param name="driveName">U盘所在盘符</param>
/// <param name="message">操作的消息</param>
/// <returns>UsbKey文件的内容</returns>
public static string ReadUsbKeyFile(string driveName, out string message)
{
if (driveName.EndsWith("//"))
driveName += "//";
string strCurrKeyFileName = driveName + Key_File_Name;
message = "";
try
{
string strResult = "";
using (StreamReader reader = File.OpenText(strCurrKeyFileName))
{
strResult = reader.ReadToEnd();
}
if (strResult != "")
{
message = "OK";
CheckCode cc = new CheckCode();
return cc.Decode(strResult);
}
else
{
message = "未能正确读取文件,文件内容可能为空!";
}
}
catch (Exception ex)
{
message = ex.Message;
}
return "";
}
}
/// <summary>
/// 检查编码情况
/// </summary>
class CheckCode
{
const string KEY_64 = "fasfgew";
const string IV_64 = "JDLJMAMI"; //注意了,是8个字符,64位
/// <summary>
/// 加密
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string Encode(string data)
{
byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64);
byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64);
DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
int i = cryptoProvider.KeySize;
MemoryStream ms = new MemoryStream();
CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cst);
sw.Write(data);
sw.Flush();
cst.FlushFinalBlock();
sw.Flush();
return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
/// <summary>
/// 解密
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string Decode(string data)
{
byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64);
byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64);
byte[] byEnc;
try
{
byEnc = Convert.FromBase64String(data);
}
catch
{
return null;
}
DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream(byEnc);
CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cst);
return sr.ReadToEnd();
}
}
在主窗体,使用下面的代码调用:private void btnMakeUsbKey_Click(object sender, EventArgs e)
{
string strMessage = "";
MakeProductNumbers();
if (UsbUtility.WriteUsbKeyFile(CurrentUSBDriveName, ProductNumbers, out strMessage))
{
MessageBox.Show("Usb Key File 生成成功!");
}
else
{
MessageBox.Show(strMessage);
}
}
private void btnShowUsbKey_Click(object sender, EventArgs e)
{
string strMessage = "";
string strText = UsbUtility.ReadUsbKeyFile(CurrentUSBDriveName, out strMessage);
if (strText!="")
{
MessageBox.Show(strText,"查看USBKEY");
}
else
{
MessageBox.Show(strMessage,"Error");
}
}
private string _CurrentUSBDriveName = "";
/// <summary>
/// 当前USB 驱动器号
/// </summary>
public string CurrentUSBDriveName
{
get
{
if (_CurrentUSBDriveName == "")
{
string[] strDrivers = Environment.GetLogicalDrives();
_CurrentUSBDriveName = strDrivers[strDrivers.Length - 1];
}
return _CurrentUSBDriveName;
}
set
{
_CurrentUSBDriveName = value ;
}
}
属性 CurrentUSBDriveName 会返回当前最后一个驱动器号,我们认为它是优盘,但是这不是很保险。为此,我们需要监视系统合适插入了U盘,并取得它的盘符。在主窗体中(一定要在主窗体中,不能再用户控件中),加入下面的代码:public const int WM_DEVICECHANGE = 0x219;
public const int DBT_DEVICEARRIVAL = 0x8000;
public const int DBT_CONFIGCHANGECANCELED = 0x0019;
public const int DBT_CONFIGCHANGED = 0x0018;
public const int DBT_CUSTOMEVENT = 0x8006;
public const int DBT_DEVICEQUERYREMOVE = 0x8001;
public const int DBT_DEVICEQUERYREMOVEFAILED = 0x8002;
public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
public const int DBT_DEVICEREMOVEPENDING = 0x8003;
public const int DBT_DEVICETYPESPECIFIC = 0x8005;
public const int DBT_DEVNODES_CHANGED = 0x0007;
public const int DBT_QUERYCHANGECONFIG = 0x0017;
public const int DBT_USERDEFINED = 0xFFFF;
protected override void WndProc(ref Message m)
{
try
{
if (m.Msg == WM_DEVICECHANGE)
{
switch (m.WParam.ToInt32())
{
case WM_DEVICECHANGE:
break;
case DBT_DEVICEARRIVAL://U盘插入
DriveInfo[] s = DriveInfo.GetDrives();
foreach (DriveInfo drive in s)
{
if (drive.DriveType == DriveType.Removable)
{
mpnUC.CurrentUSBDriveName = drive.Name.ToString();
//
MessageBox.Show("U盘已插入,盘符为:" + drive.Name.ToString() + "/r/n");
break;
}
}
break;
case DBT_CONFIGCHANGECANCELED:
break;
case DBT_CONFIGCHANGED:
break;
case DBT_CUSTOMEVENT:
break;
case DBT_DEVICEQUERYREMOVE:
break;
case DBT_DEVICEQUERYREMOVEFAILED:
break;
case DBT_DEVICEREMOVECOMPLETE: //U盘卸载
MessageBox.Show("U盘已卸载!");
break;
case DBT_DEVICEREMOVEPENDING:
break;
case DBT_DEVICETYPESPECIFIC:
break;
case DBT_DEVNODES_CHANGED:
break;
case DBT_QUERYCHANGECONFIG:
break;
case DBT_USERDEFINED:
break;
default:
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
base.WndProc(ref m);
}
mpnUC 是一个用户控件,我们设置了它的 CurrentUSBDriveName 属性。
OK,允许程序,我们就生成了一个USB Key 了。
下面的代码提供了实现该方法的途径:/// <summary>
/// USB 操作相关
/// </summary>
public class UsbUtility
{
const string Key_File_Name = "Usb.key";
/// <summary>
/// 获取优盘唯一序列号,可能需要以管理员身份运行程序
/// </summary>
/// <returns></returns>
public static string GetUSBId()
{
ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher("Select * From Win32_USBHub");
string id = "";
foreach (ManagementObject wmi_USB in wmiSearcher.Get())
{
string strPath = wmi_USB.Path.RelativePath;
string[] strArr = strPath.Split('/"');
string strTemp = strArr[1];
//VID_ 是真正的优盘标示
if (strTemp.StartsWith("USB////VID_"))
id += strTemp + ";";
}
return id.TrimEnd(';');
}
/// <summary>
/// 获取当前UsbKey,根据当前附加的序列号,生成 "序列号,UsbId"格式的字符串,并返回加密后的结果
/// 如果没有找到设备,那么返回空字符串
/// 如果返回值为空,请检查 message 的值。
/// </summary>
/// <param name="sourceNumber">要附加的序列号</param>
/// <param name="message">生成的操作信息</param>
/// <returns>当前加密后的UsbKey字符串</returns>
public static string GetCurrentUsbKey(string sourceNumber,out string message)
{
string strUsbId = GetUSBId();
if (strUsbId != "")
{
if (strUsbId.Split(';').Length == 1)
{
CheckCode cc = new CheckCode();
message = "OK";
string strTemp = sourceNumber+","+strUsbId ;
return cc.Encode(strTemp);
}
else
{
message = "当前有多个U盘,请拨除其它U盘。";
return "";
}
}
message = "未找到U盘或者U盘没有物理序列号。";
return "";
}
/// <summary>
/// 将一个新的UsbKey写到当前U盘上
/// </summary>
/// <param name="sourceNumber">U盘所在盘符</param>
/// <param name="sourceNumber">要附加的序列号</param>
/// <param name="message">生成的操作信息</param>
/// <returns></returns>
public static bool WriteUsbKeyFile(string driveName, string sourceNumber,out string message)
{
string strCurrentUsbKey = GetCurrentUsbKey(sourceNumber, out message);
if (strCurrentUsbKey != "")
{
if (driveName.EndsWith("//"))
driveName += "//";
string strCurrKeyFileName = driveName + Key_File_Name;
try
{
using (StreamWriter writer = File.CreateText(strCurrKeyFileName))
{
writer.Write(strCurrentUsbKey);
writer.Flush();
}
message = "OK";
return true;
}
catch (Exception ex)
{
message = ex.Message;
}
}
return false;
}
/// <summary>
/// 读取UsbKey文件的内容,返回内容格式为 "序列号,UsbId"格式的字符串
/// 如果未能正确读取文件,返回空字符。
/// </summary>
/// <param name="driveName">U盘所在盘符</param>
/// <param name="message">操作的消息</param>
/// <returns>UsbKey文件的内容</returns>
public static string ReadUsbKeyFile(string driveName, out string message)
{
if (driveName.EndsWith("//"))
driveName += "//";
string strCurrKeyFileName = driveName + Key_File_Name;
message = "";
try
{
string strResult = "";
using (StreamReader reader = File.OpenText(strCurrKeyFileName))
{
strResult = reader.ReadToEnd();
}
if (strResult != "")
{
message = "OK";
CheckCode cc = new CheckCode();
return cc.Decode(strResult);
}
else
{
message = "未能正确读取文件,文件内容可能为空!";
}
}
catch (Exception ex)
{
message = ex.Message;
}
return "";
}
}
/// <summary>
/// 检查编码情况
/// </summary>
class CheckCode
{
const string KEY_64 = "fasfgew";
const string IV_64 = "JDLJMAMI"; //注意了,是8个字符,64位
/// <summary>
/// 加密
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string Encode(string data)
{
byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64);
byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64);
DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
int i = cryptoProvider.KeySize;
MemoryStream ms = new MemoryStream();
CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateEncryptor(byKey, byIV), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cst);
sw.Write(data);
sw.Flush();
cst.FlushFinalBlock();
sw.Flush();
return Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
/// <summary>
/// 解密
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public string Decode(string data)
{
byte[] byKey = System.Text.ASCIIEncoding.ASCII.GetBytes(KEY_64);
byte[] byIV = System.Text.ASCIIEncoding.ASCII.GetBytes(IV_64);
byte[] byEnc;
try
{
byEnc = Convert.FromBase64String(data);
}
catch
{
return null;
}
DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream(byEnc);
CryptoStream cst = new CryptoStream(ms, cryptoProvider.CreateDecryptor(byKey, byIV), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cst);
return sr.ReadToEnd();
}
}
在主窗体,使用下面的代码调用:private void btnMakeUsbKey_Click(object sender, EventArgs e)
{
string strMessage = "";
MakeProductNumbers();
if (UsbUtility.WriteUsbKeyFile(CurrentUSBDriveName, ProductNumbers, out strMessage))
{
MessageBox.Show("Usb Key File 生成成功!");
}
else
{
MessageBox.Show(strMessage);
}
}
private void btnShowUsbKey_Click(object sender, EventArgs e)
{
string strMessage = "";
string strText = UsbUtility.ReadUsbKeyFile(CurrentUSBDriveName, out strMessage);
if (strText!="")
{
MessageBox.Show(strText,"查看USBKEY");
}
else
{
MessageBox.Show(strMessage,"Error");
}
}
private string _CurrentUSBDriveName = "";
/// <summary>
/// 当前USB 驱动器号
/// </summary>
public string CurrentUSBDriveName
{
get
{
if (_CurrentUSBDriveName == "")
{
string[] strDrivers = Environment.GetLogicalDrives();
_CurrentUSBDriveName = strDrivers[strDrivers.Length - 1];
}
return _CurrentUSBDriveName;
}
set
{
_CurrentUSBDriveName = value ;
}
}
属性 CurrentUSBDriveName 会返回当前最后一个驱动器号,我们认为它是优盘,但是这不是很保险。为此,我们需要监视系统合适插入了U盘,并取得它的盘符。在主窗体中(一定要在主窗体中,不能再用户控件中),加入下面的代码:public const int WM_DEVICECHANGE = 0x219;
public const int DBT_DEVICEARRIVAL = 0x8000;
public const int DBT_CONFIGCHANGECANCELED = 0x0019;
public const int DBT_CONFIGCHANGED = 0x0018;
public const int DBT_CUSTOMEVENT = 0x8006;
public const int DBT_DEVICEQUERYREMOVE = 0x8001;
public const int DBT_DEVICEQUERYREMOVEFAILED = 0x8002;
public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
public const int DBT_DEVICEREMOVEPENDING = 0x8003;
public const int DBT_DEVICETYPESPECIFIC = 0x8005;
public const int DBT_DEVNODES_CHANGED = 0x0007;
public const int DBT_QUERYCHANGECONFIG = 0x0017;
public const int DBT_USERDEFINED = 0xFFFF;
protected override void WndProc(ref Message m)
{
try
{
if (m.Msg == WM_DEVICECHANGE)
{
switch (m.WParam.ToInt32())
{
case WM_DEVICECHANGE:
break;
case DBT_DEVICEARRIVAL://U盘插入
DriveInfo[] s = DriveInfo.GetDrives();
foreach (DriveInfo drive in s)
{
if (drive.DriveType == DriveType.Removable)
{
mpnUC.CurrentUSBDriveName = drive.Name.ToString();
//
MessageBox.Show("U盘已插入,盘符为:" + drive.Name.ToString() + "/r/n");
break;
}
}
break;
case DBT_CONFIGCHANGECANCELED:
break;
case DBT_CONFIGCHANGED:
break;
case DBT_CUSTOMEVENT:
break;
case DBT_DEVICEQUERYREMOVE:
break;
case DBT_DEVICEQUERYREMOVEFAILED:
break;
case DBT_DEVICEREMOVECOMPLETE: //U盘卸载
MessageBox.Show("U盘已卸载!");
break;
case DBT_DEVICEREMOVEPENDING:
break;
case DBT_DEVICETYPESPECIFIC:
break;
case DBT_DEVNODES_CHANGED:
break;
case DBT_QUERYCHANGECONFIG:
break;
case DBT_USERDEFINED:
break;
default:
break;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
base.WndProc(ref m);
}
mpnUC 是一个用户控件,我们设置了它的 CurrentUSBDriveName 属性。
OK,允许程序,我们就生成了一个USB Key 了。
相关文章推荐
- 根据网卡MAC地址生成序列号
- odoo根据当前时间自动生成序列号
- 根据MAC地址生成软件的序列号
- VB根据硬盘序列号生成唯一注册码
- SBO根据一定原则,自动生成序列号
- odoo根据当前时间生成序列号
- SSH项目根据实体类Bean自动生成Action、ServiceInter、ServiceImpl类的方法
- 使用axis1.X根据WSDL地址生成客户端调用代码
- 根据wsdl生成客户端Bean的两种方式
- mybatis如何根据mapper接口生成其实现类
- 根据当月数据库自动生成下个月数据库--1
- phprap中根据DB结构生成和表中属性命名相同的接口参数
- 根据数据表中数据,生成Powerpoint幻灯片
- 分享:根据webservice WSDL地址自动生成java调用代码及JAR包
- 从零学python系列之教你如何根据图片生成字符画
- 根据数据库表生成javabean的eclipse小插件 eclipse可能找不到javabean小工具
- 详解Jquery EasyUI tree 的异步加载(遍历指定文件夹,根据文件夹内的文件生成tree)
- FlashBuild4序列号生成与使用方法
- ABAP根据输入的表名动态生成上传EXCEL数据的代码
- php根据一个给定范围和步进生成数组的方法