跳转至

安全变量

介绍

本页面描述了Hercules的安全变量功能。
在使用安全变量功能之前,您首先需要提前设置Hive SDK。
安全变量具有以下特性:

  • 这是一个存储在内存中的加密值,以便外部工具无法检索。
  • 即使加密值被篡改,在读取时也会进行验证。
  • 支持的语言包括 C/C++ 和 C#(Unity)。

如何使用安全变量

C# (Unity)

  • 基本上,C# 中可用的数据类型可以用作泛型类。
  • 有与每种数据类型相匹配的安全数据类型,如下所示。
  • 由于所有基本类型都被转换为 8 字节类型,因此建议使用 8 字节类型,例如使用 long 代替 int,使用 double 代替 float。
基本类型 安全类型 基本类型 安全类型
bool HerculesVar<bool> int HerculesVar<int>
char HerculesVar<char> uint HerculesVar<uint>
sbyte HerculesVar<sbyte> long HerculesVar<long>
byte HerculesVar<byte> ulong HerculesVar<ulong>
short HerculesVar<short> float HerculesVar<float>
ushort HerculesVar<ushort> double HerculesVar<double>
string HerculesString
// 以下两个代码做相同的事情并分配一个新对象。
HerculesVar x = 100;
HerculesVar y = new HerculesVar(100);

// 值从安全变量复制到普通变量。
int a = x;
// 释放分配给 y 的旧对象,并将新对象重新分配给 y。
y = 300;
// 更改 y 的值。(y 应该已经分配了一个对象,这种分配比上面的快。)
y.Set(300);

// y 被重新赋值为 x 的值。x 和 y 都开始引用与原始分配给 x 的对象不同的对象。  
y = (int)x;

// 注意:y 将引用 x。如果您使用 Set 函数,则两个值都会被替换。
// 如果在直接操作无符号类型安全变量时发生构建错误
// 必须在常量后指定 U,或者您应该使用显式转换。(如 1U 或 (uint)1)
// 对于频繁更新的值,使用 obj.Set(v); 形式更有利于性能。
y = x;

// 字符串可以这样使用:仅内存中的字符串受到保护。
// 当分配一个静态字符串如“TEST”时,原始字符串可能会暴露给代码。
HerculesString securityString = <从服务器下载或动态生成的字符串值>;
string plainString = securityString;

iOS, Android

  • 在 C 语言中,每当你保存或读取变量的值时,必须直接调用 API,因此建议使用 C++。C++ 定义了一个模板类。
  • 如果可能,建议将安全变量作为全局变量使用,或在分配和释放不太频繁的地方使用。
  • 不要将包含语句放在外部 "C" 块内。
  • 应在 Hive SDK 初始化后使用。
#include "Hercules.h"

class CUserInfo {
public:
    CHercules hp;
    CHercules mp;
    CHercules critical;
};

// 如果将其用作全局变量,则会出现问题,因为该变量在 Hive SDK 初始化之前尝试初始化。
// CHercules g_temp;

// 当将其用作全局变量时,按如下形式声明为指针。
CUserInfo *g_user;
CHercules *g_var;
CHerculesString *g_string;

void BeginBattle() {
    // 创建一个安全变量。 (示例:在游戏中开始战斗时)
    g_user = new CUserInfo;
    g_var = new CHercules;
    g_string = new CHerculesString(<从服务器下载的字符串值或动态生成的>);
}

void EndBattle() {
    // 删除安全变量。 (示例:在游戏战斗结束时)
    delete g_user;
    delete g_var;
    delete g_string;
    g_user = nullptr;
    
}

void Sample()
{
    // 可以以任何形式进行赋值,如下所示。
    int localvar = 0;
    CHercules x = localvar;
    *g_var = localvar;
    *g_var = x + 2;
    g_user->hp = 100;

    // 当分配一个静态字符串如“TEST”时,原始字符串可能会暴露给代码。
    CHerculesString localString1 = <从服务器下载的新字符串或动态生成的字符串>; // 初始化为字符串
    CHerculesString localString2 = *g_securityString; // 初始化为CHerculesString对象
    std::string localString = *g_securityString; // CHerculesString转换为std::string
    localString2 = localString1; // CHerculesString到CHerculesString
    localString1 = localString.c_str(); // std::string到CHerculesString
}
#include "Hercules.h"

HERCULES g_x;
HERCULES g_y;
HERCULES g_str;

void StartApp() {
    // 创建一个安全变量。
    // 可以通过放置基本类型和结构变量来使用。
    int var = 0;
    g_x = HerculesAddVar(&var, sizeof(var));
    g_y = HerculesAddVar(&var, sizeof(var));

    // 当分配一个静态字符串如“TEST”时,原始字符串可能会暴露给代码。
    g_str = HerculesAddString(<从服务器下载的字符串或动态生成的字符串>);
}

void Sample()
{
    // 获取 x 的值并将其存储在 y 中。此时,每个函数中设置的第二个参数
    // 必须是与调用 HerculesAddVar 时设置的大小相同的变量。
    int var;
    HerculesGetVar(g_x, &var);
    HerculesSetVar(g_y, &var);

    // 在将安全字符串作为常规字符串获取后,您需要使用 HerculesFreeMem 函数释放它。
    char *str = HerculesGetString(g_str);
    HerculesFreeMem(str);

    // 在分配一个新的字符串变量之前,必须使用 HerculesRemoveVar 函数删除它。
    HerculesRemoveVar(g_str);
    g_str = HerculesAddString(<从服务器下载的新字符串或动态生成的字符串>);
}

参考 (C++)

  • 当安全变量被初始化为一个值时使用它。 (对象被分配的状态)
  • 将其用作分配最终结果,该结果是在完成所有必要计算后生成的。
  • 请参阅下面的示例。 (C++ 有运算符重载。)
// CHercules *securityVar = ...

int sum = 0;
int values[5] = {5, 4, 6, 8, 11};

for(int i = 0; i < 5; i++)
    sum += values[i];

*securityVar += sum;
// CHercules *securityVar = ...

int values[5] = {5, 4, 6, 8, 11};

for(int i = 0; i < 5; i++)
    *securityVar += values[i];