콘텐츠로 이동

보안변수 적용

개요

본 문서는 허큘리스 제품의 보안 변수 기능을 설명하는 문서입니다.
보안 변수 기능을 사용하기 전에 먼저 Hive SDK 적용을 완료해야 합니다.
보안 변수의 특징은 다음과 같습니다.

  • 메모리에서 특정 값이 외부 툴에 의해 검색되지 않도록 값을 암호화 합니다.
  • 암호화 한 값이 변조되더라도 값을 읽을 때 유효한 값 인지 검증합니다.
  • 지원 언어는 C/C++ 과 C#(Unity) 이 있습니다.

보안 변수 사용

C# (Unity)

  • 기본적으로 C#에서 사용 가능한 데이터형을 Generic 클래스로 사용할 수 있습니다.
  • 각 데이터 형에 매칭되는 보안 데이터 형이 아래와 같이 있습니다.
  • 기본타입은 모두 8바이트 타입으로 캐스팅 되므로 int대신 long을, float 대신 double을 사용하는 등의 8바이트 타입 사용을 권장합니다.
Basic Type Secured Type Basic Type Secured Type
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 = 300;    
// y의 값을 변경합니다. (y에 객체가 할당되어 있어야 하며 위의 경우보다 빠릅니다.)
y.Set(300);  

// y가 x의 값으로 재할당 되어 서로 다른 객체를 참조합니다.
y = (int)x;

// 주의: y는 x를 참조하게 됩니다. Set함수를 사용하면 두 값이 모두 바뀝니다.
// unsigned 타입의 보안변수에 직접 연산할 때 빌드 에러가 발생하는 경우
// 명시적 캐스팅 또는 상수 뒤에 U를 명시해야 합니다. (1U 또는 (uint)1 의 형태로)
// 자주 갱신되는 값인 경우 obj.Set(v); 형태로 사용하는 것이 성능 향상에 유리합니다.
y = x;       

// 문자열은 아래와 같이 사용할 수 있습니다. 메모리상의 문자열만 보호가 됩니다.
// “TEST” 형태의 정적 문자열을 대입하는 경우 원본 문자열이 코드에 노출될 수 있습니다.
HerculesString securityString = <서버에서 내려받거나 동적으로 생성된 문자열 >;
string plainString = securityString;

iOS, Android

  • C의 경우는 변수의 값을 저장하거나 읽을 때 마다 API를 직접 호출해야 하므로 C++ 사용을 권장합니다. C++에는 템플릿 클래스가 정의되어 있습니다.
  • 보안 변수를 잦은 할당과 해제가 이루어 지지 않는 곳에 위치시킨 후 사용하는 것이 좋습니다.
  • include 구문을 extern "C" 블럭 안에 넣으면 안 됩니다.
  • Hive SDK가 초기화 된 이후에 사용해야 합니다.
#include "Hercules.h"

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

// 전역변수 형태로 사용하면 HiveSDK 초기화 전에 변수 초기화를 시도하여 문제가 발생합니다.
// 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에 저장합니다. 이때 각 함수에 설정되는 2번째 매개변수는
    // 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];