Qt 实现软件授权验证机制:基于硬件绑定与时效控制的方案

在软件开发中,如何保护知识产权、控制软件使用权限是开发者经常面临的问题。本文将基于 Qt 框架,介绍一种简单有效的软件授权验证机制,该机制通过硬件绑定、时效控制和防篡改等手段,实现对软件使用权限的管理。

方案设计思路

本方案主要包含以下几个核心功能:

  • 基于硬件信息生成唯一设备标识
  • 记录软件首次运行时间,实现时效控制
  • 防止用户通过修改系统时间绕过时效限制
  • 将授权信息存储在隐藏目录中,提高安全性

核心代码实现

1. 接口类定义

首先定义一个哈希接口类HashInterface,提供单例实例和有效性验证方法:

// hashinterface.h
#pragma once

#include "hashinterface_global.h"

class HASHINTERFACE_EXPORT HashInterface
{
public:
    HashInterface() = default;

    bool validity();
    static HashInterface& instance();
};

2. 硬件唯一标识生成

通过获取设备硬件信息(如磁盘序列号、CPU 信息等),生成唯一的设备标识,实现软件与设备的绑定:

// 生成设备唯一标识
QString getMachineID()
{
    // 获取硬件序列号(Windows)
    QStorageInfo storage = QStorageInfo::root();
    QString diskSerial = storage.device();

    // 获取CPU信息(可根据不同系统扩展)
    QString cpuInfo = LISENCE_TAIL;

    // 合并硬件信息并生成哈希
    QString uniqueData = diskSerial + cpuInfo;
    QByteArray hash = QCryptographicHash::hash(uniqueData.toUtf8(), QCryptographicHash::Sha256);
    return QString(hash.toHex());
}

3. 授权文件存储

将授权信息存储在隐藏目录中,提高非授权用户的修改难度:

QString getHiddenStoragePath()
{
    // 获取用户数据目录(隐藏目录)
    QString basePath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);

    // 生成随机隐藏子目录名
    QString hiddenDirName = QString("App%1").arg(QChar(0x20)) + "Data";
    QString hiddenDirPath = QDir(basePath).filePath(hiddenDirName);

    // 创建目录并设置隐藏属性
    if (!QDir(hiddenDirPath).exists())
    {
        QDir().mkpath(hiddenDirPath);
        QProcess::execute("attrib", QStringList() << "+h" << hiddenDirPath);
    }
    return hiddenDirPath;
}

4. 时效控制实现

记录软件首次运行时间,并在每次启动时校验是否过期:

// 首次运行记录时间
void saveFirstRunTime()
{
    QDateTime installTime = QDateTime::currentDateTime();
    QString machineId = getMachineID();

    // 加密数据(示例使用Base64,实际应使用AES等更强加密)
    QByteArray data = (installTime.toString(Qt::ISODate) + "|" + machineId).toUtf8();
    data = data.toBase64();

    // 存储到本地文件
    saveLisenceData(data);
}

// 每次启动校验时间
bool checkExpiration()
{
    // 读取加密文件
    QByteArray data = getLisenceData();
    QStringList parts = QString(data).split("|");
    QDateTime installTime = QDateTime::fromString(parts[0], Qt::ISODate);
    QString storeMachineID = parts[1];
    QString currentMachineID = getMachineID();

    // 校验设备标识
    if (storeMachineID != currentMachineID)
    {
        return false;
    }

    // 计算使用天数
    qint64 daysElapsed = installTime.daysTo(QDateTime::currentDateTime());
#ifdef QT_DEBUG
    printf("[Attention] It has been running for %d days and has only %d  days left!\n", daysElapsed, LISENCE_DAYS - daysElapsed);
#endif
    return (daysElapsed <= LISENCE_DAYS);
}

5. 防时间篡改机制

通过记录上次运行时间,防止用户通过修改系统时间绕过时效限制:

// 保存上次运行时间
void saveLastRunTime()
{
    QDateTime currentTime = QDateTime::currentDateTime();
    QSettings settings(APP_COMPANY, APP_NAME);
    settings.setValue(APP_PARAM, currentTime);
}

// 检查时间完整性
bool checkTimeIntegrity()
{
    QSettings settings(APP_COMPANY, APP_NAME);
    QDateTime lastRunTime = settings.value(APP_PARAM).toDateTime();
    QDateTime currentTime = QDateTime::currentDateTime();;
    if (currentTime < lastRunTime)
    {
        return false;
    }
    return true;
}

6. 验证入口函数

将上述功能整合,提供统一的验证入口:

bool HashInterface::validity()
{
    if (!isLisenceDataExist())
    {
        // 首次运行,保存初始信息
        saveFirstRunTime();
    }
    else
    {
        // 非首次运行,验证授权
        if (!checkExpiration() || !checkTimeIntegrity())
        {
            printf("[ERROR] Expiration of registration code ,please contact developer!");
            return false;
        }
    }
    // 保存本次运行时间,用于下次验证
    saveLastRunTime();
    return true;
}

// 单例实现
HashInterface& HashInterface::instance()
{
    static HashInterface manager;
    return manager;
}

使用方法

在软件启动时,只需调用以下代码进行授权验证:

if (!HashInterface::instance().validity()) {
    // 验证失败,处理逻辑(如退出程序)
    return -1;
}
// 验证成功,继续运行程序

安全性考虑

  1. 示例中使用了简单的 Base64 编码,实际应用中应使用 AES 等加密算法
  2. 硬件信息的获取可以根据不同操作系统进行扩展,提高唯一性
  3. 隐藏目录的命名方式可以进一步优化,增加隐蔽性
  4. 可以增加授权文件的签名验证,防止文件被篡改

总结

本方案通过硬件绑定、时效控制和防篡改等多重机制,实现了一个基础的软件授权验证系统。开发者可以根据实际需求,在此基础上扩展更复杂的授权逻辑,如网络验证、授权码激活等功能,进一步提高软件的安全性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值