最近接了一个需求要用到USB狗这种方式来对特定用户进行授权,公司给了一个类似U盘的东西和一个工具包,然后就让开干了
看了文档后发现好像没有直接使用的Go SDK,所以就只能使用人家提供的API和dll库了,go加载dll库有好几种方式,下面记录一下懒加载的这种,代码如下:
C API
// 找到设备
findHardware(
unsigned char* hid, //入参:设备id
int * count // 出参:查找到的设备个数
)
返回值:
0x01:执行成功,返回设备个数。// 代码:SUCCESS
0x02:没有可以用的硬件,此时 Count 值为 0。//代码:NOT_FOUND
// 打开设备
open(
HANDLE* hHandle, //出参:打开设备的句柄,返回给用户,供以后的函数调用;
unsigned char*hid, //入参:设备 id
int index // 入参:选择打开哪个设备
)
返回值:
0x01:打开成功 // 代码:SUCCESS
0x03:打开失败 //代码:OPEN_FAILED
// 获取设备中的数据
getData(
HANDLE hHandle, //入参:设备句柄
unsigned char* data //出参:返回的数据
)
返回值:
0x01:读取数据成功 // 代码:SUCCESS
0x04:读取数据失败 //代码:READ_FAILED
golang代码:
func main() {
dllPath: = "api.dll"
//判断文件存不存在
if _, err = os.Stat(dllPath); err != nil {
if os.IsExist(err) {
log.Fatalf("file not exist:%s", err)
}
log.Fatalf("%v", err)
}
// load dll,使用懒加载模式,也就是真正调用 API 的时候才会加载
lib := syscall.NewLazyDLL(dllPath)
// 找到设备
proc := lib.NewProc("findHardware")
// byte from string
str2Byte, err := syscall.BytePtrFromString("123456")
if err != nil {
log.Fatalf("change string to byte ptr failed:[%v]", err)
}
var count int
ret, _, _ := proc.Call(uintptr(unsafe.Pointer(str2Byte)), uintptr(unsafe.Pointer(&count)))
if ret == NOT_FOUND {
log.Fatalf("NOT FOUND")
}
if count == 0 {
log.Fatalf("NOT FOUND")
}
logrus.Infof("find hardware success....")
// open hardware
openFunc := lib.NewProc("open")
// get lock handler
var handler uintptr //因为不知道句柄具体类型是什么,那就用一个指针存储
ret, _, _ := openFunc.Call(uintptr(unsafe.Pointer(&handler)), uintptr(unsafe.Pointer(str2Byte)), uintptr(1))
if ret != OPEN_FAILED {
log.Fatalf("OPEN FAILED")
}
logrus.Infof("open success")
// get data
getSN := lib.NewProc("getData")
var hid [8]byte //因为返回的数据是 8 字节数组
ret, _, _ = getSN.Call(handler, uintptr(unsafe.Pointer(&hid)))
if ret != ET_SUCCESS {
log.Fatalf("Get Data Failed")
}
//将其转化成 16 进制输出
fmt.Printf("%x\n",hid)
// close hardware
closeFunc := lib.NewProc("close")
ret, _, _ = closeFunc.Call(handler)
if ret != ET_SUCCESS {
log.Fatalf("failed")
}
logrus.Infof("close success...", i)
}