#ifndef LICENSEDATA_H #define LICENSEDATA_H #include #include #include /** * @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