From 5e1e4a4b57e298806dba97175fa1fbd5c771c7cd Mon Sep 17 00:00:00 2001
From: ccy <3140717620@qq.com>
Date: 星期五, 09 十月 2026 16:17:18 +0800
Subject: [PATCH] 新的加密方式
---
licensedata.h | 25 ++++
mainwindow.cpp | 18 +-
shortcrypto.cpp | 129 +++++++++++++++++++++
shortcrypto.h | 25 ++++
licensedata.cpp | 112 ++++++++++++++++++
5 files changed, 302 insertions(+), 7 deletions(-)
diff --git a/licensedata.cpp b/licensedata.cpp
index 26d5d1b..fa31615 100644
--- a/licensedata.cpp
+++ b/licensedata.cpp
@@ -1,5 +1,7 @@
锘�#include "licensedata.h"
#include <QDataStream>
+#include <QCryptographicHash>
+#include <QRandomGenerator>
#include <QtDebug>
LicenseData::LicenseData()
@@ -105,6 +107,116 @@
.arg(activeState);
}
+// ===== V3 绱у噾鏍煎紡锛�20浣嶈鍙瘑閽ョ敤锛�=====
+
+QByteArray LicenseData::machineFingerprint(const QByteArray &uuid, const QByteArray &cpu, const QByteArray &key)
+{
+ // 涓巘oBinary鐩稿悓鐨勫畾闀胯鏁达紝淇濊瘉鎺堟潈绔拰楠岃瘉绔鍚屼竴鍙版満鍣ㄧ畻鍑哄悓涓�鎸囩汗
+ QByteArray u = uuid.left(16);
+ u.append(QByteArray(16 - u.size(), '\0'));
+ QByteArray c = cpu.left(8);
+ c.append(QByteArray(8 - c.size(), '\0'));
+
+ QCryptographicHash hash(QCryptographicHash::Sha256);
+ hash.addData(key);
+ hash.addData(u);
+ hash.addData(c);
+ return hash.result().left(8);
+}
+
+quint16 LicenseData::crc16(const QByteArray &data)
+{
+ // CRC16-CCITT (0xFFFF 鍒濆�硷紝0x1021 澶氶」寮�)
+ quint16 crc = 0xFFFF;
+ for (int i = 0; i < data.size(); ++i) {
+ crc ^= static_cast<quint16>(static_cast<unsigned char>(data.at(i))) << 8;
+ for (int b = 0; b < 8; ++b) {
+ crc = (crc & 0x8000) ? static_cast<quint16>((crc << 1) ^ 0x1021)
+ : static_cast<quint16>(crc << 1);
+ }
+ }
+ return crc;
+}
+
+QByteArray LicenseData::toBinaryV3(const QByteArray &key) const
+{
+ QByteArray data(16, '\0');
+
+ // [0..7] 鏈哄櫒鎸囩汗
+ QByteArray fp = machineFingerprint(boardUuid, cpuSerial, key);
+ memcpy(data.data(), fp.constData(), 8);
+
+ // [8..9] 澶辨晥鏃ユ湡锛堜笌V2鍚屼竴2000-01-01鍩哄噯锛�
+ quint16 days = dateToDays(expireDate);
+ data[8] = static_cast<char>((days >> 8) & 0xFF);
+ data[9] = static_cast<char>(days & 0xFF);
+
+ // [10] 浜у搧鍙�
+ data[10] = static_cast<char>(productId);
+
+ // [11] 鐗堟湰锛氶珮4浣嶄富鐗堟湰 | 浣�4浣嶆鐗堟湰
+ data[11] = static_cast<char>(((verMajor & 0x0F) << 4) | (verMinor & 0x0F));
+
+ // [12] 鏍囧織锛氶珮4浣嶆牸寮忕増鏈�(1)锛屼綆4浣嶆縺娲荤姸鎬�
+ data[12] = static_cast<char>(0x10 | (activeState & 0x0F));
+
+ // [13..14] CRC16锛堣鐩朳0..12]锛岄殢鏈虹洂涓嶅弬涓庯級
+ quint16 crc = crc16(data.left(13));
+ data[13] = static_cast<char>((crc >> 8) & 0xFF);
+ data[14] = static_cast<char>(crc & 0xFF);
+
+ // [15] 闅忔満鐩�
+ data[15] = static_cast<char>(QRandomGenerator::global()->generate() & 0xFF);
+
+ return data;
+}
+
+bool LicenseData::fromBinaryV3(const QByteArray &data)
+{
+ if (data.size() != 16) {
+ return false;
+ }
+
+ quint8 flags = static_cast<quint8>(data.at(12));
+ if ((flags >> 4) != 0x01) {
+ qWarning() << "LicenseData::fromBinaryV3: not a V3 payload, format version ="
+ << (flags >> 4);
+ return false;
+ }
+
+ quint16 expectCrc = static_cast<quint16>((static_cast<quint8>(data.at(13)) << 8)
+ | static_cast<quint8>(data.at(14)));
+ if (crc16(data.left(13)) != expectCrc) {
+ qWarning() << "LicenseData::fromBinaryV3: CRC check failed, wrong key or corrupted data";
+ return false;
+ }
+
+ machineFp = data.left(8);
+
+ quint16 days = static_cast<quint16>((static_cast<quint8>(data.at(8)) << 8)
+ | static_cast<quint8>(data.at(9)));
+ expireDate = daysToDate(days);
+
+ productId = static_cast<quint8>(data.at(10));
+
+ quint8 ver = static_cast<quint8>(data.at(11));
+ verMajor = ver >> 4;
+ verMinor = ver & 0x0F;
+
+ activeState = flags & 0x0F;
+ return true;
+}
+
+QString LicenseData::toDebugStringV3() const
+{
+ return QString("{FP:%1, Expire:%2, Prod:%3, Ver:%4.%5, State:%6}")
+ .arg(binaryToHexString(machineFp))
+ .arg(expireDate.toString("yyyy-MM-dd"))
+ .arg(productId)
+ .arg(verMajor).arg(verMinor)
+ .arg(activeState);
+}
+
quint16 LicenseData::dateToDays(const QDate &date) const
{
QDate base(BASE_YEAR, BASE_MONTH, BASE_DAY);
diff --git a/licensedata.h b/licensedata.h
index e732d3d..d964f09 100644
--- a/licensedata.h
+++ b/licensedata.h
@@ -38,6 +38,31 @@
bool fromBinary(const QByteArray &data);
QString toDebugString() const;
+ /**
+ * @brief V3 绱у噾鏍煎紡锛�28浣嶇函澶у啓璁稿彲瀵嗛挜鐢紝鎭板ソ16瀛楄妭锛�
+ *
+ * 浜岃繘鍒跺竷灞�锛堝ぇ绔簭锛夛細
+ * [0..7] 8B 鏈哄櫒鎸囩汗 = SHA256(瀵嗛挜鈥朥UID(16B)鈥朇PU(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 闅忔満鐩愶紙閬垮厤鍚屾満鍚屾棩鏈熷瘑鏂囧畬鍏ㄧ浉鍚岋級
+ *
+ * 涓嶸2鐨勫尯鍒細UUID/CPU涓嶅啀鏄庢枃闅忓瘑閽ユ惡甯︼紝鍙甫涓嶅彲閫嗘寚绾癸紱
+ * 璁惧ID浠嶇敤V2鏍煎紡锛堥渶瑕佽繕鍘熸満鍣ㄤ俊鎭級锛屼粎璁稿彲瀵嗛挜鐢╒3銆�
+ */
+ QByteArray toBinaryV3(const QByteArray &key) const;
+ bool fromBinaryV3(const QByteArray &data);
+ QString toDebugStringV3() const;
+
+ QByteArray machineFp; // V3瑙e嚭鐨勬満鍣ㄦ寚绾癸紙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);
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 1292e42..93e1d2d 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -279,7 +279,6 @@
QString encryptlocalid = ui->textEdit_localid->toPlainText();
// 涓�閿В瀵�
lic2.fromBinary(ShortCrypto::decrypt(encryptlocalid, key));
- qDebug()<<"on_pushButton_decrypt_clicked"<<lic2.toDebugString();
//涓庝箣鍓嶇殑鍔犲瘑瀵瑰簲,涓斿幓鎺夊啑浣欎俊鎭�
localinfo.Baseboard_Uuid = LicenseData::uuidBinaryToString(lic2.boardUuid);
localinfo.CPU_Processorid = LicenseData::binaryToHexString(lic2.cpuSerial);
@@ -536,13 +535,18 @@
lic2.expireDate = QDate::fromString(licensedatestr,"yyyy-MM-dd");
// lic2.expireDate = lic2.expireDate.addMonths(time);
lic2.activeState = 1;
- QString cipher = ShortCrypto::encrypt(lic2.toBinary(), key);
+ // V3绱у噾鏍煎紡锛�28浣嶇函澶у啓锛夛細鏈哄櫒淇℃伅浠ユ寚绾瑰舰寮忕粦瀹�
+ QString cipher = ShortCrypto::encryptRaw(lic2.toBinaryV3(key), key);
ui->textEdit_licensekey->clear();
ui->textEdit_licensekey->setPlainText(cipher);
- // 涓�閿В瀵�
+ // 鍔犲瘑鍚庤嚜妫�
LicenseData lic3;
- lic3.fromBinary(ShortCrypto::decrypt(cipher, key));
- qDebug()<<"change"<<cipher<<lic3.toDebugString()<<cipher.size();
+ if (lic3.fromBinaryV3(ShortCrypto::decryptRaw(cipher, key))) {
+ qDebug() << "V3鑷閫氳繃:" << lic3.toDebugStringV3();
+ } else {
+ qWarning() << "V3鑷澶辫触";
+ }
+
//鏇存柊licenseinfo锛屽彧闇�瑕佹洿鏂癓icensedDuration_end銆丩icensedDuration_start銆丄ctiveState
licenseinfo.LicensedDuration_end = newlicensedate.toString("yyyy-MM-dd");
licenseinfo.LicensedDuration_start = licensedate.toString("yyyy-MM-dd");
@@ -791,7 +795,7 @@
// ui->textEdit_licensekey->setPlainText(getEncrypt(QString(testid),key));
lic2.productId = ui->lineEdit_setproid->text().toUInt();
- QString cipher = ShortCrypto::encrypt(lic2.toBinary(), key);
+ QString cipher = ShortCrypto::encryptRaw(lic2.toBinaryV3(key), key);
ui->textEdit_licensekey->setPlainText(cipher);
// setLicenseinfo(licensekey_Obj);
@@ -817,7 +821,7 @@
QString version = ui->lineEdit_setversion->text();
lic2.verMajor = version.split(".").at(0).toUInt();
lic2.verMinor = version.split(".").at(1).toUInt();
- QString cipher = ShortCrypto::encrypt(lic2.toBinary(), key);
+ QString cipher = ShortCrypto::encryptRaw(lic2.toBinaryV3(key), key);
ui->textEdit_licensekey->setPlainText(cipher);
//閫欒!涔熷彧闇�瑕佹洿鏂癡ersionid
licenseinfo.Versionid = ui->lineEdit_setversion->text();
diff --git a/shortcrypto.cpp b/shortcrypto.cpp
index 796fcb8..e6d80fd 100644
--- a/shortcrypto.cpp
+++ b/shortcrypto.cpp
@@ -1,10 +1,16 @@
锘�#include "shortcrypto.h"
#include "tinyaes.h"
#include <QtDebug>
+#include <QtMath>
+#include <algorithm>
// Base85 瀛楃闆嗭細85涓彲鎵撳嵃瀛楃锛岄伩寮�瀹规槗鍦║RL/JSON閲屽嚭闂鐨勫瓧绗�
const char *ShortCrypto::BASE85_CHARS =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~";
+
+// V3 瀛楃闆嗭細绾ぇ鍐欏瓧姣嶏紙26瀛楃锛夛紝璁稿彲瀵嗛挜鍙惈 A-Z锛�28浣�
+const char *ShortCrypto::V3_CHARS =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
namespace {
QByteArray pkcs7Pad(const QByteArray &data, int blockSize) {
@@ -105,6 +111,129 @@
return pkcs7Unpad(decrypted);
}
+QString ShortCrypto::encryptRaw(const QByteArray &plaintext, const QByteArray &key)
+{
+ if (key.size() != 16) {
+ qWarning() << "ShortCrypto::encryptRaw: key must be 16 bytes for AES-128";
+ return QString();
+ }
+ if (plaintext.isEmpty() || plaintext.size() % 16 != 0) {
+ qWarning() << "ShortCrypto::encryptRaw: plaintext size must be a non-zero multiple of 16, got"
+ << plaintext.size();
+ return QString();
+ }
+
+ // 鍗曞潡鏃跺叏闆禝V鐨凜BC绛変环浜嶦CB锛涘鍧楁椂涓篊BC閾炬帴
+ QByteArray adjustedIv(16, '\0');
+
+ QByteArray encrypted = plaintext;
+ struct AES_ctx ctx;
+ AES_init_ctx_iv(&ctx, reinterpret_cast<const uint8_t*>(key.constData()),
+ reinterpret_cast<const uint8_t*>(adjustedIv.constData()));
+ AES_CBC_encrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(encrypted.data()), encrypted.size());
+
+ // 绾ぇ鍐欏瓧姣嶇紪鐮侊細16瀛楄妭瀵嗘枃 鈫� 28瀛楃锛堣嫢鍏佽鏁板瓧鎹�36瀛楃闆嗭紝闀垮害闄嶅埌25锛�
+ QByteArray encoded = baseNEncode(encrypted, V3_CHARS, 26);
+ return QString::fromLatin1(encoded);
+}
+
+QByteArray ShortCrypto::decryptRaw(const QString &ciphertext, const QByteArray &key)
+{
+ if (key.size() != 16) {
+ qWarning() << "ShortCrypto::decryptRaw: key must be 16 bytes for AES-128";
+ return QByteArray();
+ }
+
+ // 浼樺厛鎸夌函瀛楁瘝琛ㄨВ鐮侊紱鑻ュ惈琛ㄥ瀛楃锛堟棭鏈烞ase85鐗圴3瀵嗛挜锛夊垯鍥為��Base85
+ QByteArray encrypted = baseNDecode(ciphertext, V3_CHARS, 26);
+ if (encrypted.isEmpty()) {
+ encrypted = base85Decode(ciphertext);
+ }
+ if (encrypted.isEmpty()) {
+ qWarning() << "ShortCrypto::decryptRaw: decode failed";
+ return QByteArray();
+ }
+ if (encrypted.size() % 16 != 0) {
+ qWarning() << "ShortCrypto::decryptRaw: decoded data size not aligned to block size:"
+ << encrypted.size();
+ return QByteArray();
+ }
+
+ QByteArray adjustedIv(16, '\0');
+ QByteArray decrypted = encrypted;
+ struct AES_ctx ctx;
+ AES_init_ctx_iv(&ctx, reinterpret_cast<const uint8_t*>(key.constData()),
+ reinterpret_cast<const uint8_t*>(adjustedIv.constData()));
+ AES_CBC_decrypt_buffer(&ctx, reinterpret_cast<uint8_t*>(decrypted.data()), decrypted.size());
+ return decrypted;
+}
+
+QByteArray ShortCrypto::baseNEncode(const QByteArray &data, const char *alphabet, int base)
+{
+ // 鎶婃暣娈靛ぇ绔瓧鑺傚簭褰撲綔涓�涓ぇ鏁存暟锛岄�愭闄や互base鍙栦綑鏁�
+ QByteArray num = data;
+ QByteArray remainders;
+
+ bool isZero = false;
+ while (!isZero) {
+ isZero = true;
+ unsigned int carry = 0;
+ for (int i = 0; i < num.size(); ++i) {
+ unsigned int cur = (carry << 8) | static_cast<unsigned char>(num.at(i));
+ num[i] = static_cast<char>(cur / static_cast<unsigned int>(base));
+ carry = cur % static_cast<unsigned int>(base);
+ if (num.at(i) != 0) isZero = false;
+ }
+ if (isZero && remainders.isEmpty()) break; // 鍏ㄩ浂杈撳叆
+ remainders.append(alphabet[static_cast<int>(carry)]);
+ if (isZero) break;
+ }
+ if (remainders.isEmpty()) remainders.append(alphabet[0]);
+
+ // 杩樺師涓洪珮浣嶅湪鍓嶏紝骞剁敤alphabet[0]琛ラ綈鍥哄畾浣嶆暟锛堝墠瀵奸浂锛�
+ QByteArray result = remainders;
+ std::reverse(result.begin(), result.end());
+ int minimalLen = static_cast<int>(qCeil(data.size() * 8.0 * qLn(2.0) / qLn(static_cast<double>(base))));
+ if (result.size() < minimalLen) {
+ result.prepend(QByteArray(minimalLen - result.size(), alphabet[0]));
+ }
+ return result;
+}
+
+QByteArray ShortCrypto::baseNDecode(const QString &text, const char *alphabet, int base)
+{
+ // 寤虹珛瀛楃绱㈠紩琛�
+ int charToVal[256];
+ memset(charToVal, -1, sizeof(charToVal));
+ for (int i = 0; i < base; ++i) {
+ charToVal[static_cast<unsigned char>(alphabet[i])] = i;
+ }
+
+ // Horner娉曞垯锛歯um = num * base + v锛堝ぇ绔瓧鑺傚簭锛�
+ QByteArray num(16, '\0');
+ QByteArray input = text.toLatin1();
+ for (int i = 0; i < input.size(); ++i) {
+ int v = charToVal[static_cast<unsigned char>(input.at(i))];
+ if (v < 0) {
+ qWarning() << "ShortCrypto::baseNDecode: invalid character:" << QChar(input.at(i));
+ return QByteArray();
+ }
+ unsigned int carry = static_cast<unsigned int>(v);
+ for (int b = num.size() - 1; b >= 0; --b) {
+ unsigned int cur = (static_cast<unsigned int>(static_cast<unsigned char>(num.at(b))) * static_cast<unsigned int>(base)) + carry;
+ num[b] = static_cast<char>(cur & 0xFF);
+ carry = cur >> 8;
+ }
+ if (carry != 0) {
+ qWarning() << "ShortCrypto::baseNDecode: value overflows 128 bits";
+ return QByteArray();
+ }
+ }
+
+ // 淇濇寔16瀛楄妭瀹氬锛堝墠瀵奸浂鏈夋剰涔夛級锛岃皟鐢ㄦ柟鎸夊浐瀹氬潡闀垮鐞�
+ return num;
+}
+
QByteArray ShortCrypto::base85Encode(const QByteArray &data)
{
QByteArray result;
diff --git a/shortcrypto.h b/shortcrypto.h
index 9f0756e..f34dcdd 100644
--- a/shortcrypto.h
+++ b/shortcrypto.h
@@ -29,12 +29,37 @@
*/
static QByteArray decrypt(const QString &ciphertext, const QByteArray &key, const QByteArray &iv = QByteArray());
+ /**
+ * @brief 鏃犲~鍏呭姞瀵嗭紙V3涓撶敤锛�
+ * @param plaintext 鍘熷鏄庢枃锛岄暱搴﹀繀椤绘槸16鐨勫�嶆暟锛�16瀛楄妭鏄庢枃 鈫� 16瀛楄妭瀵嗘枃锛�
+ * @param key 16瀛楄妭瀵嗛挜锛圓ES-128锛�
+ * @return 绾ぇ鍐欏瓧姣嶇紪鐮佺殑瀵嗘枃瀛楃涓诧紙A-Z锛�26瀛楃闆嗭級锛�16瀛楄妭鏄庢枃鎭板ソ杈撳嚭28瀛楃
+ * @note 涓嶅仛PKCS7濉厖锛�16瀛楄妭鏄庢枃鑻ヨ蛋濉厖浼氭墿鎴�32瀛楄妭
+ * @note 鑻ユ兂缂╃煭鍒�25瀛楃锛屾妸V3_CHARS鎹㈡垚"A-Z0-9"骞舵妸base鏀逛负36鍗冲彲
+ */
+ static QString encryptRaw(const QByteArray &plaintext, const QByteArray &key);
+
+ /**
+ * @brief 鏃犲~鍏呰В瀵嗭紙V3涓撶敤锛�
+ * @param ciphertext 绾ぇ鍐欏瓧姣嶇紪鐮佺殑瀵嗘枃锛堝吋瀹规棭鏈烞ase85/绾瓧姣嶇増V3瀵嗘枃锛岃嚜鍔ㄥ洖閫�锛�
+ * @param key 16瀛楄妭瀵嗛挜锛圓ES-128锛�
+ * @return 鍘熷鏄庢枃锛堥暱搴︿笌瀵嗘枃涓�鑷达級锛屽畬鏁存�х敱涓婂眰CRC鏍¢獙淇濊瘉
+ */
+ static QByteArray decryptRaw(const QString &ciphertext, const QByteArray &key);
+
private:
// Base85 瀛楃闆嗭紙RFC 1924 鍙樹綋锛屼笉鍚紩鍙�/閫楀彿/鍙ョ偣/鏂滄潬锛岄伩鍏岼SON/XML杞箟闂锛�
static const char *BASE85_CHARS;
+ // V3 瀵嗘枃瀛楃闆嗭細绾ぇ鍐欏瓧姣嶏紝涓嶅惈鏁板瓧/灏忓啓/鐗规畩瀛楃锛�26瀛楃闆嗭紝16瀛楄妭鈫�28瀛楃锛�
+ static const char *V3_CHARS;
+
static QByteArray base85Encode(const QByteArray &data);
static QByteArray base85Decode(const QString &text);
+
+ // 浠绘剰杩涘埗鐨勫ぇ鏁扮紪瑙g爜锛堟暣娈靛瓧鑺傚簭浣滀负澶ф暣鏁帮紝鍓嶅闆朵互alphabet[0]琛ラ綈鍥哄畾浣嶆暟锛�
+ static QByteArray baseNEncode(const QByteArray &data, const char *alphabet, int base);
+ static QByteArray baseNDecode(const QString &text, const char *alphabet, int base);
};
#endif // SHORTCRYPTO_H
--
Gitblit v1.9.1