使用工業相機好不容易做了一個項目,寫了一個漂亮的軟件。但是因爲成本原因又不能使用加密狗,軟件出售後又擔心被競爭對手直接複製。現在介紹一個方法,如果使用的工業相機滿足以下條件,即可實現加密功能。
- 每臺工業相機都具有唯一的序列號且不能更改
- 工業相機有用戶存儲空間或者用戶自定義序列號
實現原理
- 加密過程
因爲每臺相機都能保證有唯一的序列號,我們可以讀取這個序列號然後使用自定義的算法進行加密,然後將加密後的數據寫入到相機的用戶存儲空間或者用戶自定義序列號
- 解決驗證過程
打開相機讀取相機序列號,再讀取相機中存儲的加密數據。使用解密算法對加密數據進行解密,如果解密的數據與序列號一致,則說明解密成功,如果不一致,則說明有問題。
加密和解密的算法可以自己定義。
具體步驟
下面我使用雲鑰科技的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來進行驗證。最後再使用軟件加殼工具對軟件進行加殼處理,增加點破解難度。
歡迎大家使用雲鑰科技的工業相機,支持各種方案定製。