使用工业相机好不容易做了一个项目,写了一个漂亮的软件。但是因为成本原因又不能使用加密狗,软件出售后又担心被竞争对手直接复制。现在介绍一个方法,如果使用的工业相机满足以下条件,即可实现加密功能。
- 每台工业相机都具有唯一的序列号且不能更改
- 工业相机有用户存储空间或者用户自定义序列号
实现原理
- 加密过程
因为每台相机都能保证有唯一的序列号,我们可以读取这个序列号然后使用自定义的算法进行加密,然后将加密后的数据写入到相机的用户存储空间或者用户自定义序列号
- 解决验证过程
打开相机读取相机序列号,再读取相机中存储的加密数据。使用解密算法对加密数据进行解密,如果解密的数据与序列号一致,则说明解密成功,如果不一致,则说明有问题。
加密和解密的算法可以自己定义。
具体步骤
下面我使用云钥科技的CK工业相机的SDK编写相应的代码,为了演示,加密算法非常简单,只是将序列号进行按位取反。
加密过程
使用visual studio 2015的代码样例
// CameraEncrypt.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include "CKCameraInterface.h"
#ifdef WIN32
#pragma comment(lib, "CKCameraDLL.lib")
#else
#pragma comment(lib, "CKCameraDLL_x64.lib")
#endif
#include <iostream>
using namespace std;
int CameraEncrypt()
{
int nCameraNum;
CameraSdkStatus status;
//打开相机前必须调用这个函数来搜索相机
status = CameraEnumerateDevice(&nCameraNum);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "enumerate camera failed" << endl;
return -1;
}
printf("Found cameras number: %d\n", nCameraNum);
//打开相机
HANDLE hCamera;
status = CameraInit(&hCamera, 0);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "open camera failed!" << endl;
return -1;
}
//读取工业相机序列号
BYTE szSn[32];
status = CameraReadSN(hCamera, szSn, 0);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "read sn failed!" << endl;
CameraUnInit(hCamera);
return -1;
}
printf("Camera SN: %s\n", (char*)szSn);
//加密过程
int nLen = strlen((char*)szSn);
//这里为了演示,使用非常简单的加密算法,直接将SN按位取反当成加密后的数据
BYTE szEncryptData [32];
for (int i = 0; i < nLen; i++)
szEncryptData[i] = ~szSn[i];
//将加密数据保存到用户自定义序列号1
status = CameraWriteSN(hCamera, szEncryptData, 1);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "write user sn1 failed" << endl;
CameraUnInit(hCamera);
return -1;
}
//关闭相机
CameraUnInit(hCamera);
cout << "encrypt finish" << endl;
return 0;
}
int main()
{
CameraEncrypt();
getchar();
return 0;
}
解密校验过程
使用visual stduio 编写的样例
// CameraDecrypt.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include "CKCameraInterface.h"
#ifdef WIN32
#pragma comment(lib, "CKCameraDLL.lib")
#else
#pragma comment(lib, "CKCameraDLL_x64.lib")
#endif
#include <iostream>
using namespace std;
HANDLE OpenCamera()
{
int nCameraNum;
CameraSdkStatus status;
//打开相机前必须调用这个函数来搜索相机
status = CameraEnumerateDevice(&nCameraNum);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "enumerate camera failed" << endl;
return NULL;
}
printf("Found cameras number: %d\n", nCameraNum);
//打开相机
HANDLE hCamera;
status = CameraInit(&hCamera, 0);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "open camera failed!" << endl;
return NULL;
}
return hCamera;
}
void CloseCamera(HANDLE hCamera)
{
CameraUnInit(hCamera);
}
int CameraVerify(HANDLE hCamera)
{
//读取工业相机序列号
BYTE szSn[32];
CameraSdkStatus status = CameraReadSN(hCamera, szSn, 0);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "read sn failed!" << endl;
return -1;
}
printf("Camera SN: %s\n", (char*)szSn);
BYTE szUserSn1[32];
status = CameraReadSN(hCamera, szUserSn1, 1);
if (status != CAMERA_STATUS_SUCCESS)
{
cout << "read user sn1 failed!" << endl;
return -1;
}
//解密过程
int nLen = strlen((char*)szSn);
for (int i = 0; i < nLen; i++) {
if (~szUserSn1[i] != szSn[i])
return -2;
}
//cout << "decrypt finish" << endl;
return 0;
}
int main()
{
HANDLE hCamera = OpenCamera();
if (hCamera == NULL)
return -1;
int nRet = CameraVerify(hCamera);
if (nRet == -2)
{
//相机验证失败,直接退出程序
exit(-2);
}
else if(nRet < 0)
{
//相机其它错误,提示相应的信息
}
else
{
//验证成功
}
//其它图像算法和功能......
CloseCamera(hCamera);
getchar();
return 0;
}
工程软件可以在很多地方调用CameraVerify来进行验证。最后再使用软件加壳工具对软件进行加壳处理,增加点破解难度。
欢迎大家使用云钥科技的工业相机,支持各种方案定制。