首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

cocos2d-x 存檔防作弊:使用 SHA-1 摘要演算法進行資料完整性校驗

     編輯:關於C語言

為何需要存檔校驗?

CCUserDefault 以明文 XML 儲存遊戲資料(金幣、等級、道具),玩家可直接修改 UserDefault.xml 作弊。引入摘要演算法(Hash)可偵測資料竄改:寫入時計算資料+密鑰的摘要並存檔;讀取時重新計算比對,不一致即判定作弊。

選擇 SHA-1 與輕量庫

常見摘要演算法有 MD5、SHA-1、SHA-256。SHA-1 安全性足夠應對單機遊戲,且有極輕量的實現(tamale.net 提供 sha1.h/cpp 兩檔案,無第三方依賴)。

整合步驟

1. 專案加入 SHA-1 原始碼

下載 sha1.h、sha1.cpp 加入專案,並確保編譯選項支援 C++11。

2. 開啟主控台輸出(方便除錯)

// AppDelegate.cpp
#include <tchar.h>

bool AppDelegate::applicationDidFinishLaunching() {
    _tsetlocale(LC_ALL, _T(""));
    ::AllocConsole();
    ::freopen("conout$", "w", stdout);
    // ... 原有初始化程式碼
}

3. 寫入帶校驗的存檔


#define SAVE_KEY "goldlion"   // 硬編碼密鑰,實際專案建議加密或動態生成
#define SAVE_TAG "player_gold"

void SaveWithHash(int gold) {
    CCUserDefault* save = CCUserDefault::sharedUserDefault();
    char buf[32];
    sprintf(buf, "%d", gold);
    save->setStringForKey(SAVE_TAG, buf);

    // 計算 SHA-1(data + key)
    SHA1* sha1 = new SHA1();
    sha1->addBytes(buf, strlen(buf));
    sha1->addBytes(SAVE_KEY, strlen(SAVE_KEY));
    unsigned char* digest = sha1->getDigest();   // 20 bytes

    // 存儲十六進位摘要
    char hexDigest[41];
    for (int i = 0; i < 20; ++i) sprintf(hexDigest + i*2, "%02x", digest[i]);
    save->setStringForKey(std::string(SAVE_TAG) + "_hash", hexDigest);

    delete sha1;
    free(digest);
    save->flush();
}

4. 讀取並驗證


bool LoadWithHash(int& outGold) {
    CCUserDefault* save = CCUserDefault::sharedUserDefault();
    std::string data = save->getStringForKey(SAVE_TAG);
    std::string storedHash = save->getStringForKey(std::string(SAVE_TAG) + "_hash");

    SHA1* sha1 = new SHA1();
    sha1->addBytes(data.c_str(), data.length());
    sha1->addBytes(SAVE_KEY, strlen(SAVE_KEY));
    unsigned char* digest = sha1->getDigest();

    char calcHash[41];
    for (int i = 0; i < 20; ++i) sprintf(calcHash + i*2, "%02x", digest[i]);

    delete sha1;
    free(digest);

    if (storedHash != calcHash) {
        CCLOG("存檔校驗失敗:資料已被竄改!");
        return false;
    }
    outGold = atoi(data.c_str());
    return true;
}

實測驗證

  1. 正常遊戲存檔 → 讀取校驗通過。
  2. 手動修改 UserDefault.xml 中的 player_gold 值 → 讀取時校驗失敗,偵測到作弊。

正常存檔校驗碼 讀取校驗通過 手動修改 XML 校驗失敗偵測

工程化建議

  1. 封裝通用介面:提供 SetIntegerForKeyWithHash、GetIntegerForKeyWithHash 等模板函數,支援 int、float、bool 等型別。
  2. 加入開關控制:以巨集 ENABLE_SAVE_VERIFY 控制校驗開關,測試階段關閉方便修改存檔,發布時開啟。
  3. 密鑰保護:密鑰勿硬編碼於單一字串,可拆分、混淆、或從程式碼特徵動態生成,提高逆向難度。
  4. 網遊存檔:核心資料應放伺服器端,本地僅存非關鍵快取,仍建議加密傳輸。

總結

SHA-1 摘要加密鑰的方式,以極低成本實現了存檔防篡改。雖非絕對安全(客戶端程式碼可被逆向),但足以阻擋 99% 普通玩家的修改器作弊,是單機遊戲存檔保護的性價比之選。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved