GrabBag/Module/AuthModule/Src/AuthManager.cpp

139 lines
4.8 KiB
C++
Raw Normal View History

2026-01-25 01:27:01 +08:00
#include "AuthManager.h"
#include "AuthConfig.h"
#include "VrLog.h"
#include <QCryptographicHash>
#include <QString>
#include <QFile>
#include <QDir>
#include <QDateTime>
#include <QProcess>
static QString md5(const QString& s) {
return QCryptographicHash::hash(s.toUtf8(), QCryptographicHash::Md5).toHex();
}
static QString encrypt(const QString& text, const QString& key) {
QByteArray t = text.toUtf8(), k = key.toUtf8(), r;
for (int i = 0; i < t.size(); ++i) r.append(t[i] ^ k[i % k.size()]);
return r.toBase64();
}
static QString decrypt(const QString& text, const QString& key) {
QByteArray t = QByteArray::fromBase64(text.toUtf8()), k = key.toUtf8(), r;
for (int i = 0; i < t.size(); ++i) r.append(t[i] ^ k[i % k.size()]);
return QString::fromUtf8(r);
}
static QString exec(const QString& cmd) {
QProcess p;
#ifdef _WIN32
p.start("cmd", {"/c", cmd});
#else
p.start("sh", {"-c", cmd});
#endif
p.waitForFinished();
return QString(p.readAllStandardOutput()).remove('\r').remove('\n').remove(' ');
}
static QString cpuSerial() {
#ifdef _WIN32
QString r = exec(WMIC_CMD_CPU_SERIAL);
r.remove("ProcessorId");
#else
QString r = exec("cat /proc/cpuinfo | grep Serial | awk '{print $3}'");
#endif
return md5(r);
}
static QString diskSerial() {
#ifdef _WIN32
QString r = exec(WMIC_CMD_DISK_SERIAL);
r.remove("SerialNumber");
#else
// ARM: 优先读取 eMMC/SD 卡 CID其次读取 SATA 硬盘序列号
QString r = exec("cat /sys/block/mmcblk0/device/cid 2>/dev/null || "
"cat /sys/block/sda/device/serial 2>/dev/null || "
"cat /sys/class/dmi/id/product_serial 2>/dev/null || echo 'unknown'");
#endif
return r.remove("0000").remove('_').remove('.');
}
static QString getFilePath() {
return QDir::homePath() + "/" + AUTH_FILE_PATH;
}
std::string AuthManager::GetMachineCode() {
QString cpu = cpuSerial(), disk = diskSerial();
QString combined = (cpu + disk).left(40).toUpper();
LOG_INFO("cpu: %s, disk: %s \n", qPrintable(cpu), qPrintable(disk));
QString result;
for (int i = 0; i < combined.length(); i += 8) {
if (!result.isEmpty()) result += "-";
result += combined.mid(i, 8);
}
return result.toStdString();
}
std::string AuthManager::GenerateLicenseKey(const std::string& machineCode, const std::string& expireDate) {
QString mc = QString::fromStdString(machineCode), ed = QString::fromStdString(expireDate);
QString key = md5(mc + "|" + ed);
QString hash = md5(AUTH_KEY_SEED + key + ed).toUpper();
return encrypt(ed + "|" + hash, AUTH_KEY_SEED).toStdString();
}
bool AuthManager::SaveLicenseInfo(const std::string& licenseKey, const std::string& /*expireDate*/) {
#ifndef _WIN32
QDir().mkpath(QDir::homePath() + "/.config");
#endif
QString filePath = getFilePath();
QFile f(filePath);
if (!f.open(QIODevice::WriteOnly)) {
LOG_WARN("Failed to open file %s for writing", qPrintable(filePath));
return false;
}
f.write(QString::fromStdString(licenseKey).toUtf8());
return true;
}
bool AuthManager::LoadLicenseInfo(std::string& licenseKey, std::string& expireDate) {
QString filePath = getFilePath();
QFile f(filePath);
if (!f.open(QIODevice::ReadOnly)) {
LOG_WARN("Failed to open file %s for reading\n", qPrintable(filePath));
return false;
}
licenseKey = QString(f.readAll()).trimmed().toStdString();
// 从授权码中解析过期日期
QString decoded = decrypt(QString::fromStdString(licenseKey), AUTH_KEY_SEED);
int pos = decoded.indexOf('|');
if (pos == -1) return false;
expireDate = decoded.left(pos).toStdString();
return true;
}
bool AuthManager::CheckLicenseValid() {
std::string lk, ed;
if (!LoadLicenseInfo(lk, ed)) return false;
return ValidateLicenseKey(lk, ed);
}
bool AuthManager::ValidateLicenseKey(const std::string& licenseKey, std::string& expireDate) {
QString decoded = decrypt(QString::fromStdString(licenseKey), AUTH_KEY_SEED);
int pos = decoded.indexOf('|');
if (pos == -1) return false;
QString expDate = decoded.left(pos);
// 验证过期日期格式
if (expDate != PERMANENT_LICENSE_DATE && expDate.length() != 8) return false;
// 验证授权码是否匹配当前机器
std::string expectedKey = GenerateLicenseKey(GetMachineCode(), expDate.toStdString());
if (QString::fromStdString(expectedKey).toUpper() != QString::fromStdString(licenseKey).toUpper()) return false;
// 验证是否过期
if (expDate != PERMANENT_LICENSE_DATE && QDate::currentDate().toString("yyyyMMdd") > expDate) return false;
expireDate = expDate.toStdString();
return true;
}