보안변수 적용
개요¶
본 문서는 허큘리스 제품의 보안 변수 기능을 설명하는 문서입니다.
보안 변수 기능을 사용하기 전에 먼저 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++은 연산자 오버로딩이 되어 있습니다.)