c++ 代码验证事例

创建时间: 2025-08-18 08:42:00
更新时间: 2025-08-19 06:32:41
#include <windows.h>
#include <wincrypt.h>
#include <iphlpapi.h>
#include <intrin.h>
#include <VersionHelpers.h>
#include <rpc.h>
#include <winhttp.h>
#include <string>
#include <vector>
#include <iomanip>
#include <sstream>
#include <iostream>
#include <nlohmann/json.hpp>
// 感谢 Yume 提出的openssl 会被hook的bug 欢迎进他的群 868318886 
// 需要libs的联系Fonnt 或者 自己vcpkg下载
// 最新一次更新 8.17 21.06
#pragma comment(lib, "winhttp.lib")
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "Rpcrt4.lib")

#define BASE_URL L"lifey.icu"
#define PORT 80
#define APP_ID "您的appid"
#define SECRET "您项目的加密密钥"
#define AES_BLOCK_SIZE 16
#define AES_KEY_SIZE 32

using json = nlohmann::json;

void setupConsoleEncoding() {
    SetConsoleOutputCP(CP_UTF8);
    SetConsoleCP(CP_UTF8);

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hConsole != INVALID_HANDLE_VALUE) {
        CONSOLE_FONT_INFOEX fontInfo = { 0 };
        fontInfo.cbSize = sizeof(CONSOLE_FONT_INFOEX);
        if (GetCurrentConsoleFontEx(hConsole, FALSE, &fontInfo)) {
            wcscpy_s(fontInfo.FaceName, L"SimHei");
            SetCurrentConsoleFontEx(hConsole, FALSE, &fontInfo);
        }
    }
}

namespace CustomBase64 {
    static const std::string base64_chars =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";

    static inline bool is_base64(unsigned char c) {
        return (isalnum(c) || (c == '+') || (c == '/'));
    }

    std::string encode(const std::string& input) {
        std::string ret;
        int i = 0;
        int j = 0;
        unsigned char char_array_3[3];
        unsigned char char_array_4[4];
        size_t in_len = input.size();
        const char* bytes_to_encode = input.data();

        while (in_len--) {
            char_array_3[i++] = *(bytes_to_encode++);
            if (i == 3) {
                char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
                char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
                char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
                char_array_4[3] = char_array_3[2] & 0x3f;

                for (i = 0; (i < 4); i++)
                    ret += base64_chars[char_array_4[i]];
                i = 0;
            }
        }

        if (i) {
            for (j = i; j < 3; j++)
                char_array_3[j] = '\0';

            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for (j = 0; (j < i + 1); j++)
                ret += base64_chars[char_array_4[j]];

            while ((i++ < 3))
                ret += '=';
        }

        return ret;
    }

    std::string decode(const std::string& encoded_string) {
        size_t in_len = encoded_string.size();
        int i = 0;
        int j = 0;
        int in_ = 0;
        unsigned char char_array_4[4], char_array_3[3];
        std::string ret;

        while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
            char_array_4[i++] = encoded_string[in_]; in_++;
            if (i == 4) {
                for (i = 0; i < 4; i++)
                    char_array_4[i] = static_cast<unsigned char>(base64_chars.find(char_array_4[i]));

                char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
                char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
                char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

                for (i = 0; (i < 3); i++)
                    ret += char_array_3[i];
                i = 0;
            }
        }

        if (i) {
            for (j = i; j < 4; j++)
                char_array_4[j] = 0;

            for (j = 0; j < 4; j++)
                char_array_4[j] = static_cast<unsigned char>(base64_chars.find(char_array_4[j]));

            char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
            char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
            char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];

            for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
        }

        return ret;
    }
}

void secureRandomBytes(BYTE* buf, size_t len) {
    HCRYPTPROV hProv;
    if (CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
        CryptGenRandom(hProv, (DWORD)len, buf);
        CryptReleaseContext(hProv, 0);
    }
}

void printByteArray(const BYTE* data, size_t len, const std::string& label) {
    std::cout << label << ": ";
    for (size_t i = 0; i < len; ++i) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)data[i];
    }
    std::cout << std::dec << std::endl;
}

class SecureAES {
private:
    std::vector<BYTE> key;

    void prepareKey(const std::string& secret) {
        std::string decodedKey = CustomBase64::decode(secret);
        std::cout << "密钥Base64解码后长度: " << decodedKey.size() << "字节" << std::endl;

        std::vector<BYTE> tempKey(decodedKey.begin(), decodedKey.end());

        if (tempKey.size() < AES_KEY_SIZE) {
            std::cout << "密钥长度不足" << AES_KEY_SIZE << "字节,补充至" << AES_KEY_SIZE << "字节" << std::endl;
            tempKey.resize(AES_KEY_SIZE, 0x00);
        }
        else if (tempKey.size() > AES_KEY_SIZE) {
            std::cout << "密钥长度超过" << AES_KEY_SIZE << "字节,截断至" << AES_KEY_SIZE << "字节" << std::endl;
            tempKey.resize(AES_KEY_SIZE);
        }

        key = tempKey;
        printByteArray(key.data(), key.size(), "最终使用的AES密钥");
    }

public:
    SecureAES(const std::string& secret) {
        prepareKey(secret);
    }

    std::string encrypt(const std::string& plaintext) {
        HCRYPTPROV hProv = NULL;
        HCRYPTKEY hKey = NULL;
        DWORD dwMode = CRYPT_MODE_CBC;

        BYTE iv[AES_BLOCK_SIZE];
        secureRandomBytes(iv, AES_BLOCK_SIZE);
        printByteArray(iv, AES_BLOCK_SIZE, "生成的IV");

        if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
            std::cerr << "CryptAcquireContext失败: " << GetLastError() << std::endl;
            return "";
        }

        DWORD keyLen = (DWORD)key.size();
        std::vector<BYTE> keyBlob;

        BLOBHEADER bh;
        bh.bType = PLAINTEXTKEYBLOB;
        bh.bVersion = CUR_BLOB_VERSION;
        bh.reserved = 0;
        bh.aiKeyAlg = CALG_AES_256;

        DWORD blobSize = sizeof(BLOBHEADER) + sizeof(DWORD) + keyLen;
        keyBlob.resize(blobSize);

        memcpy(keyBlob.data(), &bh, sizeof(BLOBHEADER));
        memcpy(keyBlob.data() + sizeof(BLOBHEADER), &keyLen, sizeof(DWORD));
        memcpy(keyBlob.data() + sizeof(BLOBHEADER) + sizeof(DWORD), key.data(), keyLen);

        if (!CryptImportKey(hProv, keyBlob.data(), blobSize, 0, 0, &hKey)) {
            std::cerr << "CryptImportKey失败: " << GetLastError() << std::endl;
            CryptReleaseContext(hProv, 0);
            return "";
        }

        if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0) ||
            !CryptSetKeyParam(hKey, KP_IV, iv, 0)) {
            std::cerr << "CryptSetKeyParam失败: " << GetLastError() << std::endl;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 0);
            return "";
        }

        DWORD dwDataLen = (DWORD)plaintext.size();
        DWORD dwBufLen = dwDataLen + AES_BLOCK_SIZE;
        std::vector<BYTE> ciphertext(dwBufLen);
        memcpy(ciphertext.data(), plaintext.data(), dwDataLen);

        if (!CryptEncrypt(hKey, 0, TRUE, 0, ciphertext.data(), &dwDataLen, dwBufLen)) {
            std::cerr << "CryptEncrypt失败: " << GetLastError() << std::endl;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 0);
            return "";
        }

        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 0);

        std::vector<BYTE> combined;
        combined.insert(combined.end(), iv, iv + AES_BLOCK_SIZE);
        combined.insert(combined.end(), ciphertext.begin(), ciphertext.begin() + dwDataLen);

        std::string encrypted = CustomBase64::encode(std::string(combined.begin(), combined.end()));
        std::cout << "加密后的数据长度: " << encrypted.size() << "字节" << std::endl;
        return encrypted;
    }

    std::string decrypt(const std::string& ciphertext) {
        std::string decoded = CustomBase64::decode(ciphertext);
        std::cout << "解密时Base64解码后的数据长度: " << decoded.size() << "字节" << std::endl;

        if (decoded.size() <= AES_BLOCK_SIZE) {
            std::cerr << "密文长度不足" << std::endl;
            return "";
        }

        const BYTE* iv = reinterpret_cast<const BYTE*>(decoded.data());
        const BYTE* encryptedData = iv + AES_BLOCK_SIZE;
        DWORD encryptedDataLen = (DWORD)(decoded.size() - AES_BLOCK_SIZE);
        printByteArray(iv, AES_BLOCK_SIZE, "解密使用的IV");

        HCRYPTPROV hProv = NULL;
        HCRYPTKEY hKey = NULL;
        DWORD dwMode = CRYPT_MODE_CBC;

        if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
            std::cerr << "CryptAcquireContext失败: " << GetLastError() << std::endl;
            return "";
        }

        DWORD keyLen = (DWORD)key.size();
        std::vector<BYTE> keyBlob;

        BLOBHEADER bh;
        bh.bType = PLAINTEXTKEYBLOB;
        bh.bVersion = CUR_BLOB_VERSION;
        bh.reserved = 0;
        bh.aiKeyAlg = CALG_AES_256;

        DWORD blobSize = sizeof(BLOBHEADER) + sizeof(DWORD) + keyLen;
        keyBlob.resize(blobSize);

        memcpy(keyBlob.data(), &bh, sizeof(BLOBHEADER));
        memcpy(keyBlob.data() + sizeof(BLOBHEADER), &keyLen, sizeof(DWORD));
        memcpy(keyBlob.data() + sizeof(BLOBHEADER) + sizeof(DWORD), key.data(), keyLen);

        if (!CryptImportKey(hProv, keyBlob.data(), blobSize, 0, 0, &hKey)) {
            std::cerr << "CryptImportKey失败: " << GetLastError() << std::endl;
            CryptReleaseContext(hProv, 0);
            return "";
        }

        if (!CryptSetKeyParam(hKey, KP_MODE, (BYTE*)&dwMode, 0) ||
            !CryptSetKeyParam(hKey, KP_IV, (BYTE*)iv, 0)) {
            std::cerr << "CryptSetKeyParam失败: " << GetLastError() << std::endl;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 0);
            return "";
        }

        DWORD dwDataLen = encryptedDataLen;
        std::vector<BYTE> plaintext(dwDataLen);
        memcpy(plaintext.data(), encryptedData, dwDataLen);

        if (!CryptDecrypt(hKey, 0, TRUE, 0, plaintext.data(), &dwDataLen)) {
            std::cerr << "CryptDecrypt失败: " << GetLastError() << std::endl;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 0);
            return "";
        }

        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 0);

        return std::string(plaintext.begin(), plaintext.begin() + dwDataLen);
    }
};

std::string getDeviceFingerprint() {
    std::string deviceInfo;

    deviceInfo = "Windows";
    if (IsWindows10OrGreater()) {
        deviceInfo += "-10+";
    }
    else if (IsWindows8Point1OrGreater()) {
        deviceInfo += "-8.1";
    }
    else if (IsWindows8OrGreater()) {
        deviceInfo += "-8";
    }
    else if (IsWindows7OrGreater()) {
        deviceInfo += "-7";
    }
    else if (IsWindowsVistaOrGreater()) {
        deviceInfo += "-Vista";
    }
    else if (IsWindowsXPOrGreater()) {
        deviceInfo += "-XP";
    }
    else {
        deviceInfo += "-Unknown";
    }

    int cpuInfo[4] = { -1 };
    __cpuid(cpuInfo, 1);
    char cpuId[32];
    snprintf(cpuId, sizeof(cpuId), "%08X%08X", cpuInfo[3], cpuInfo[0]);
    deviceInfo += "-cpu:";
    deviceInfo += cpuId;

    IP_ADAPTER_INFO adapterInfo[16];
    ULONG bufLen = sizeof(adapterInfo);
    if (GetAdaptersInfo(adapterInfo, &bufLen) == ERROR_SUCCESS) {
        PIP_ADAPTER_INFO pAdapterInfo = adapterInfo;
        char macAddr[18];
        snprintf(macAddr, sizeof(macAddr), "%02X-%02X-%02X-%02X-%02X-%02X",
            pAdapterInfo->Address[0], pAdapterInfo->Address[1],
            pAdapterInfo->Address[2], pAdapterInfo->Address[3],
            pAdapterInfo->Address[4], pAdapterInfo->Address[5]);
        deviceInfo += "-mac:";
        deviceInfo += macAddr;
    }

    HCRYPTPROV hProv = 0;
    HCRYPTHASH hHash = 0;
    BYTE rgbHash[32];
    DWORD cbHash = 32;
    CHAR rgbDigits[] = "0123456789abcdef";

    if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
        return "";
    }

    if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
        CryptReleaseContext(hProv, 0);
        return "";
    }

    if (!CryptHashData(hHash, (BYTE*)deviceInfo.c_str(), (DWORD)deviceInfo.size(), 0)) {
        CryptDestroyHash(hHash);
        CryptReleaseContext(hProv, 0);
        return "";
    }

    if (!CryptGetHashParam(hHash, HP_HASHVAL, rgbHash, &cbHash, 0)) {
        CryptDestroyHash(hHash);
        CryptReleaseContext(hProv, 0);
        return "";
    }

    std::stringstream ss;
    for (DWORD i = 0; i < cbHash; i++) {
        ss << rgbDigits[rgbHash[i] >> 4] << rgbDigits[rgbHash[i] & 0xf];
    }

    CryptDestroyHash(hHash);
    CryptReleaseContext(hProv, 0);

    return ss.str();
}

std::string generateUUID() {
    UUID uuid;
    UuidCreate(&uuid);

    RPC_CSTR str;
    UuidToStringA(&uuid, &str);

    std::string result(reinterpret_cast<char*>(str));
    RpcStringFreeA(&str);
    return result;
}

class SecureClientSession {
private:
    std::string sessionId;
    std::string sessionKey;
    long long expireTime = 0;
    std::string token;
    std::string appId;
    std::string secret;
    SecureAES aes;

    json buildSecureRequest(const std::string& path, const json& payload) {
        json payloadCopy = payload;
        payloadCopy["timestamp"] = static_cast<long long>(time(nullptr) * 1000);
        payloadCopy["nonce"] = generateUUID();

        std::string payloadStr = payloadCopy.dump();
        std::cout << "发送的原始数据: " << payloadStr << std::endl;

        std::string encrypted = aes.encrypt(payloadStr);

        return {
            {"encrypted_data", encrypted},
            {"appid", appId},
            {"encryption_key", secret}
        };
    }

    json sendSecureRequest(const std::string& path, const json& payload) {
        json req = buildSecureRequest(path, payload);
        std::string reqStr = req.dump();
        std::cout << "发送的请求数据大小: " << reqStr.size() << "字节" << std::endl;

        HINTERNET hSession = WinHttpOpen(L"SecureClient/1.0",
            WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
            WINHTTP_NO_PROXY_NAME,
            WINHTTP_NO_PROXY_BYPASS, 0);

        if (!hSession) {
            std::cerr << "WinHttpOpen失败: " << GetLastError() << std::endl;
            return nullptr;
        }

        HINTERNET hConnect = WinHttpConnect(hSession, BASE_URL, PORT, 0);
        if (!hConnect) {
            std::cerr << "WinHttpConnect失败: " << GetLastError() << std::endl;
            WinHttpCloseHandle(hSession);
            return nullptr;
        }

        std::wstring widePath(path.begin(), path.end());
        HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"POST", widePath.c_str(),
            NULL, WINHTTP_NO_REFERER,
            WINHTTP_DEFAULT_ACCEPT_TYPES,
            0);
        if (!hRequest) {
            std::cerr << "WinHttpOpenRequest失败: " << GetLastError() << std::endl;
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return nullptr;
        }

        std::wstring headers = L"Content-Type: application/json; charset=utf-8";
        if (!WinHttpAddRequestHeaders(hRequest, headers.c_str(), (DWORD)headers.length(), WINHTTP_ADDREQ_FLAG_ADD)) {
            std::cerr << "WinHttpAddRequestHeaders失败: " << GetLastError() << std::endl;
        }

        std::string response;
        if (WinHttpSendRequest(hRequest,
            WINHTTP_NO_ADDITIONAL_HEADERS, 0,
            (LPVOID)reqStr.c_str(), (DWORD)reqStr.size(),
            (DWORD)reqStr.size(), 0)) {
            if (WinHttpReceiveResponse(hRequest, NULL)) {
                DWORD dwSize = 0;
                DWORD dwDownloaded = 0;
                LPSTR pszOutBuffer;

                do {
                    dwSize = 0;
                    if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) {
                        std::cerr << "WinHttpQueryDataAvailable失败: " << GetLastError() << std::endl;
                        break;
                    }

                    pszOutBuffer = new char[dwSize + 1];
                    if (!pszOutBuffer) {
                        std::cerr << "内存分配失败" << std::endl;
                        break;
                    }

                    ZeroMemory(pszOutBuffer, dwSize + 1);
                    if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) {
                        std::cerr << "WinHttpReadData失败: " << GetLastError() << std::endl;
                        delete[] pszOutBuffer;
                        break;
                    }

                    response.append(pszOutBuffer, dwDownloaded);
                    delete[] pszOutBuffer;

                } while (dwSize > 0);
            }
            else {
                std::cerr << "WinHttpReceiveResponse失败: " << GetLastError() << std::endl;
            }
        }
        else {
            std::cerr << "WinHttpSendRequest失败: " << GetLastError() << std::endl;
        }

        WinHttpCloseHandle(hRequest);
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hSession);

        try {
            if (response.empty()) {
                std::cerr << "未收到服务器响应" << std::endl;
                return nullptr;
            }

            if (response.substr(0, 15).find("<!doctype html>") != std::string::npos) {
                std::cerr << "服务器返回错误页面,可能是密钥问题" << std::endl;
                return nullptr;
            }

            json root = json::parse(response);
            if (root.contains("encrypted_response")) {
                std::string decrypted = aes.decrypt(root["encrypted_response"].get<std::string>());
                return json::parse(decrypted);
            }
            else {
                std::cerr << "服务器响应不包含encrypted_response字段" << std::endl;
                return root;
            }
        }
        catch (const std::exception& e) {
            std::cerr << "JSON解析错误: " << e.what() << std::endl;
            std::cerr << "原始响应: " << response << std::endl;
        }
        return nullptr;
    }

public:
    SecureClientSession(const std::string& app_id, const std::string& secret)
        : appId(app_id), secret(secret), aes(secret) {
    }

    bool activateCard(const std::string& cardKey) {
        json payload = {
            {"action", "activate"},
            {"card_key", cardKey},
            {"device_id", getDeviceFingerprint()},
            {"appid", appId}
        };

        json res = sendSecureRequest("/api/user/activate-card", payload);
        if (res != nullptr && res.contains("success") && res["success"].get<bool>()) {
            std::cout << "成功: " << res["message"].get<std::string>() << std::endl;
            return true;
        }
        else if (res != nullptr && res.contains("message")) {
            std::cout << "错误: " << res["message"].get<std::string>() << std::endl;
        }
        return false;
    }

    bool login(const std::string& user, const std::string& pwd) {
        json payload = {
            {"action", "login"},
            {"username", user},
            {"password", pwd},
            {"device_id", getDeviceFingerprint()},
            {"appid", appId}
        };

        json res = sendSecureRequest("/api/user/encrypted-login", payload);
        if (res != nullptr && res.contains("success") && res["success"].get<bool>()) {
            token = res["encrypted_token"].get<std::string>();
            sessionId = res["session_id"].get<std::string>();
            sessionKey = res["session_key"].get<std::string>();
            expireTime = res["expire_time"].get<long long>();
            return true;
        }
        else if (res != nullptr && res.contains("message")) {
            std::cout << "登录失败: " << res["message"].get<std::string>() << std::endl;
        }
        return false;
    }

    void printSessionInfo() {
        std::cout << "会话ID: " << sessionId << std::endl;
        time_t t = static_cast<time_t>(expireTime / 1000);

        struct tm timeinfo;
        localtime_s(&timeinfo, &t);

        char buffer[80];
        strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &timeinfo);
        std::cout << "until至: " << buffer << std::endl;
    }
};

int main() {
    setupConsoleEncoding();

    std::cout << "SECRET: " << SECRET << std::endl;

    std::string decodedSecret = CustomBase64::decode(SECRET);
    std::cout << "SECRET Base64: " << decodedSecret.size() << "bytes" << std::endl;

    SecureClientSession client(APP_ID, SECRET);

    std::string username, password;
    std::cout << "username: ";
    std::cin >> username;
    std::cout << "password: ";
    std::cin >> password;

    if (client.login(username, password)) {
        std::cout << "LoginSuccessful" << std::endl;

        std::cout << "DeviceID: " << getDeviceFingerprint() << std::endl;
        client.printSessionInfo();
    }
    else {
        std::cout << "DeviceID: " << getDeviceFingerprint() << std::endl;
        std::cout << "Login Failed" << std::endl;
    }

    system("pause");
    return 0;
}