软加密是指使用软件实现的加密算法和加密功能,而不是依赖硬件设备(如专用加密芯片)来执行加密操作。软加密通常通过软件库、算法和程序来实现数据的加密和解密,可以在通用计算设备上运行,如个人电脑、服务器和移动设备。
软加密的优点包括灵活性高、成本低、易于部署和维护。然而,由于软加密依赖于通用计算设备的处理能力,可能会受到性能和安全性方面的限制。相比之下,硬件加密通常能提供更高的性能和安全性,但成本较高且部署和维护相对复杂。
总的来说,软加密在许多情况下是一种有效的加密解决方案,特别是对于需要在通用计算设备上进行加密操作的场景。
软加密主要有三种实现方式:
本文以软加密实现的第二种方式为例,给大家展示一套简易的软加密系统实现方案:
效果展示如下:
license
。license
拷贝回客户端文本框,进行激活
license.lic
的文件license.lic
文件,进行后台自动验证;不存在或者验证失败,则弹出激活界面逻辑其实比较简单,这里只贴一贴软加密库部分的核心代码。
#ifndef LIBSOFTENCRYPT_H
#define LIBSOFTENCRYPT_H
#include "LibSoftEncrypt_global.h"
#include <iostream>
#include <string>
#include <functional>
class LIBSOFTENCRYPT_EXPORT LibSoftEncrypt
{
public:
LibSoftEncrypt();
typedef QString (*Custom_Encrypt_Func)(const QString&);
enum SoftEncryptType
{
CUSTOMER = 0x00001,
BASE64 = 0x0002,
RSA = 0x0003
};
const std::string GetHardwareID() const;
/**
* @brief generateLicense
* @param skey 机器码
* @param days 有效天数
* @param f 自定义加密函数
* @param type 加密类型,当自定义加密函数不为空时,type实际无效
* @return
*/
const QString generateLicense(const QString& skey,
time_t days,
Custom_Encrypt_Func f = nullptr,
SoftEncryptType type = BASE64) ;
/**
* @brief activeLicence
* @param lic 激活码
* @param hdwareId 硬件编码
* @return
*/
const bool activeLicence(const std::string &lic,const std::string& hdwareId ) const;
const bool activeLicence(const QString &lic,const QString& hdwareId ) const;
private:
Custom_Encrypt_Func m_f;
};
#endif // LIBSOFTENCRYPT_H
#include "libsoftencrypt.h"
#include <iostream>
#include <Windows.h>
#include <intrin.h> //__cpuid
#include <comdef.h>
#include <WbemIdl.h>
#include <QString>
#include <string>
#include "base64.h"
#include <random> // 随机字符
#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "wbemuuid.lib")
const std::string LibSoftEncrypt::GetHardwareID() const
{
std::string hardwareID;
// 获取CPU序列号
int cpuInfo[4] = { 0, 0, 0, 0 };
__cpuid(cpuInfo, 0x80000002);
for (int i = 0; i < 4; ++i) {
hardwareID += std::to_string(cpuInfo[i]);
}
// 获取硬盘序列号
DWORD volumeSerialNumber;
GetVolumeInformationA("C:\\", NULL, 0, &volumeSerialNumber, NULL, NULL, NULL, 0);
hardwareID += std::to_string(volumeSerialNumber);
// 获取网卡MAC地址
IP_ADAPTER_INFO AdapterInfo[16];
DWORD dwBufLen = sizeof(AdapterInfo);
DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen);
if (dwStatus == ERROR_SUCCESS) {
for (int i = 0; i < AdapterInfo[0].AddressLength; ++i) {
char hex[3];
sprintf(hex, "%02X", AdapterInfo[0].Address[i]);
hardwareID += hex;
}
}
return hardwareID;
}
std::string GenerateLicense_base64(const std::string& machineCode)
{
std::string s = base64_encode(machineCode);
return s;
}
LibSoftEncrypt::LibSoftEncrypt()
{
}
const QString LibSoftEncrypt::generateLicense(const QString &skey, time_t days,
Custom_Encrypt_Func f,
SoftEncryptType type)
{
/* ------------------------------------------------------------------------------------
* 0 ~ 19 20 1 21~ 21+len1 21+len1 +1 \
* ------------------------------------------------------------------------------------ \
* 20个混淆字符 | 硬件编码字符长度 char | 加密方法 char | 硬件编码 | 时间戳长度 char | \
* ------------------------------------------------------------------------------------
*
* -----------------------------------------------------
* 21+len1 +1 + len2 | 21+len1 +1 + len2 +9 |
* -----------------------------------------------------
* 截止时间戳 | 9个随机混淆字符 | =
* -----------------------------------------------------
*
*/
std::string machineCode = skey.toStdString();
time_t startTime = time(nullptr);
time_t endTime = startTime + (days * 24 * 60 * 60);
std::string license;
if(nullptr == f){
switch (type) {
case BASE64:
license = GenerateLicense_base64(machineCode);
break;
default:
break;
}
}else{
m_f = f;
license = QString(m_f(skey)).toStdString();
}
/// 加入混淆字符
auto f_mixed = [](size_t n)->std::string{
std::string charset = "abcdefghijklmnopqrstuvwxy"\
"zABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
std::string result;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, charset.size() - 1);
for (size_t i = 0; i < n; ++i) {
result += charset[dis(gen)];
}
return result;
};
std::cout << "Generated License: " << license << std::endl;
char clen_lic = license.length();
std::cout << "Generated License: " << license.length() << " ==> " << clen_lic << std::endl;
char clen_et = int(type);
license = f_mixed(20) + clen_lic + clen_et + license ;
license += std::to_string(endTime) + f_mixed(9) + "=" ;
std::cout << "Generated License: " << license << std::endl;
return QString::fromStdString(license);
}
const bool LibSoftEncrypt::activeLicence(const std::string &lic,
const std::string &hdwareId) const
{
int valid_lic_len = lic[20];
int lic_encrypt_type = lic[21];
std::string s = lic.substr(22,valid_lic_len);
/// lic is the same
switch (lic_encrypt_type) {
case BASE64:
if(s != GenerateLicense_base64(hdwareId)){
std::cerr << "invalid license!" << std::endl;
return false;
}
break;
case RAS:
break;
case CUSTOMER:
{
if(!m_f) {
return false;
}
if(QString::fromStdString(s) != m_f(QString::fromStdString(hdwareId)) ){
std::cerr << "invalid license!" << std::endl;
return false;
}
break;
}
default:
break;
}
std::cout << "activeLicence License: " << valid_lic_len << ", " << s << std::endl;
/// check timestamp
int timestampStringLen = lic[22+valid_lic_len];
std::string timestampStr = lic.substr(22+valid_lic_len,timestampStringLen);
time_t endtime = std::stoll(timestampStr);
time_t curtTime = time(nullptr);
if(curtTime > endtime){
std::cerr << "The license has expired!" << std::endl;
return false;
}
return true;
}
const bool LibSoftEncrypt::activeLicence(const QString &lic,
const QString& hdwareId) const
{
return activeLicence(lic.toStdString(),hdwareId.toStdString());
}
加密算法,这里简单采用base64,其他加密算法的实现,自行补充,不过后续博主也会逐渐完善的哈。
常见的加密算法普一下:
软加密除了一些加密算法库的使用之外,我们在生成lic证书的协议格式上同样可以做一些“手脚”,譬如字符混淆等等。聪明的你们肯定有更多的好方法和好主意,可以留言指导一二,不胜感激~