ccy
6 天以前 5e1e4a4b57e298806dba97175fa1fbd5c771c7cd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#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