一、什么是软加密

软加密是指使用软件实现的加密算法和加密功能,而不是依赖硬件设备(如专用加密芯片)来执行加密操作。软加密通常通过软件库、算法和程序来实现数据的加密和解密,可以在通用计算设备上运行,如个人电脑、服务器和移动设备。

软加密的优点包括灵活性高、成本低、易于部署和维护。然而,由于软加密依赖于通用计算设备的处理能力,可能会受到性能和安全性方面的限制。相比之下,硬件加密通常能提供更高的性能和安全性,但成本较高且部署和维护相对复杂。

总的来说,软加密在许多情况下是一种有效的加密解决方案,特别是对于需要在通用计算设备上进行加密操作的场景。

二、软加密的实现

软加密主要有三种实现方式:

  • 1、软件授权不与计算机硬件特征绑定。具体还分为两种:一是采用与一个软信息,如用户名等绑定的方式,一般用于个人用户授权;二是不绑定任何信息,只要序列号或授权文件验证通过,软件可以在任何机器上使用,通常用于大客户批量授权。授权的验证方式有直接比较、算法变换比较等方式。
  • 2、软件授权与计算机硬件特征绑定。绑定的计算机硬件特征主要有CPU序列号、BIOS序列号、硬盘序列号、网卡MAC地址等。这种保护方式的许可证文件是在获得了计算机的硬件特征以后,由授权服务器将硬件特征与授权内容绑定后生成的。这种绑定计算机硬件的加密方式,如果使用类似网银数字证书的公私钥保护机制,是很难破解的。
  • 3、软件授权与互联网上的授权服务器绑定。是云计算模式的授权方案,也称云授权。云授权的安全强度非常高,甚至比加密锁还要高。这是因为加密锁随软件卖出去后是无法跟踪和监测的,黑客可以花任意长的时间去破解它,而且一旦破解了可以大批量复制。而授权服务器有防火墙和完善的入侵检测技术,任何非法的访问和异常情况都可以监测得到,安全性要高的多。服务器授权也便于实现授权软件的跟踪管理、破解补救和升级更新。

三、软加密实现示例

本文以软加密实现的第二种方式为例,给大家展示一套简易的软加密系统实现方案:
软加密的设计和简单实现示例-LMLPHP
效果展示如下:
软加密的设计和简单实现示例-LMLPHP

  • 在客户端生成对应的机器码
  • 将生成的机器码拷贝到服务端界面,选择lic的有效期限(自生成时间开始算起),生成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,其他加密算法的实现,自行补充,不过后续博主也会逐渐完善的哈。
常见的加密算法普一下:

  • RSA是一种非对称加密算法,它使用一对密钥(公钥和私钥)来加密和解密数据。公钥用于加密数据,私钥用于解密数据。RSA算法也可以用于数字签名和密钥交换。RSA算法的安全性基于大整数分解的困难性,即将一个大的合数分解为其质因数的难度。RSA算法的安全性取决于密钥的长度,通常使用较长的密钥长度以提供更高的安全性。RSA算法在许多领域得到了广泛应用,包括安全通信、数字签名、身份验证等
  • AES(高级加密标准)是一种对称加密算法,被广泛应用于保护数据的安全性。它是一种块加密算法,能够以128位、192位或256位的密钥长度来加密数据块。AES算法使用相同的密钥来加密和解密数据,因此被称为对称加密算法。AES算法的安全性和性能都得到了广泛认可,它已成为许多安全通信协议和加密软件的首选算法。AES算法在许多领域得到了广泛应用,包括网络通信、数据库加密、文件加密等。

三、小结

软加密除了一些加密算法库的使用之外,我们在生成lic证书的协议格式上同样可以做一些“手脚”,譬如字符混淆等等。聪明的你们肯定有更多的好方法和好主意,可以留言指导一二,不胜感激~

01-04 14:23