#ifndef LICENSEDATA_H
|
#define LICENSEDATA_H
|
|
#include <QByteArray>
|
#include <QString>
|
#include <QDate>
|
|
/**
|
* @brief 许可证数据结构 V2(极致紧凑版)
|
*
|
* 二进制格式(大端序):
|
* [0..15] 16B 主板UUID(原始二进制)
|
* [16..23] 8B CPU序列号(原始二进制)
|
* [24] 1B 用户名长度N
|
* [25..24+N] N B 用户名UTF-8数据
|
* [25+N..26+N] 2B 失效日期(距2000-01-01的天数,uint16)
|
* [27+N] 1B 产品号(uint8)
|
* [28+N] 1B 主版本号(uint8)
|
* [29+N] 1B 次版本号(uint8)
|
* [30+N] 1B 激活状态(uint8)
|
*
|
* 总长度 = 31 + N 字节
|
*/
|
struct LicenseData
|
{
|
QByteArray boardUuid; // 16字节二进制UUID
|
QByteArray cpuSerial; // 8字节二进制
|
QString userName; // 用户名
|
QDate expireDate; // 失效日期(仅日期,无时间)
|
quint8 productId; // 产品号
|
quint8 verMajor; // 主版本号
|
quint8 verMinor; // 次版本号
|
quint8 activeState; // 激活状态
|
|
LicenseData();
|
|
QByteArray toBinary() const;
|
bool fromBinary(const QByteArray &data);
|
QString toDebugString() const;
|
|
/**
|
* @brief V3 紧凑格式(28位纯大写许可密钥用,恰好16字节)
|
*
|
* 二进制布局(大端序):
|
* [0..7] 8B 机器指纹 = SHA256(密钥‖UUID(16B)‖CPU(8B)) 截断前8字节
|
* [8..9] 2B 失效日期(距2000-01-01的天数,uint16,与V2同基准)
|
* [10] 1B 产品号
|
* [11] 1B 版本号(高4位主版本 | 低4位次版本)
|
* [12] 1B 标志(高4位格式版本=1,低4位激活状态)
|
* [13..14] 2B CRC16-CCITT(覆盖[0..12])
|
* [15] 1B 随机盐(避免同机同日期密文完全相同)
|
*
|
* 与V2的区别:UUID/CPU不再明文随密钥携带,只带不可逆指纹;
|
* 设备ID仍用V2格式(需要还原机器信息),仅许可密钥用V3。
|
*/
|
QByteArray toBinaryV3(const QByteArray &key) const;
|
bool fromBinaryV3(const QByteArray &data);
|
QString toDebugStringV3() const;
|
|
QByteArray machineFp; // V3解出的机器指纹(8字节);V2中为空
|
|
// 机器指纹:授权端与验证端必须用同一算法、同一密钥
|
static QByteArray machineFingerprint(const QByteArray &uuid, const QByteArray &cpu, const QByteArray &key);
|
static quint16 crc16(const QByteArray &data);
|
|
// 辅助转换
|
static QByteArray uuidStringToBinary(const QString &uuidStr);
|
static QString uuidBinaryToString(const QByteArray &bin);
|
static QByteArray hexStringToBinary(const QString &hexStr);
|
static QString binaryToHexString(const QByteArray &bin);
|
|
private:
|
// 日期基准:2000-01-01,用uint16存天数,范围 2000-01-01 ~ 2182-06-05
|
static constexpr int BASE_YEAR = 2000;
|
static constexpr int BASE_MONTH = 1;
|
static constexpr int BASE_DAY = 1;
|
|
quint16 dateToDays(const QDate &date) const;
|
QDate daysToDate(quint16 days) const;
|
};
|
|
#endif // LICENSEDATA_H
|