개요
본 문서는 허큘리스 제품의 보안 변수 기능을 설명하는 문서입니다.
보안 변수 기능을 사용하기 전에 먼저 Hive SDK 적용을 완료해야 합니다.
보안 변수의 특징은 다음과 같습니다.
- 메모리에서 특정 값이 외부 툴에 의해 검색되지 않도록 값을 암호화 합니다.
- 암호화 한 값이 변조되더라도 값을 읽을 때 유효한 값 인지 검증합니다.
- 지원 언어는 C/C++ 과 C#(Unity) 이 있습니다.
보안 변수 사용
C# (Unity)용
- 기본적으로 C#에서 사용 가능한 데이터형을 Generic 클래스로 사용할 수 있습니다.
- 각 데이터 형에 매칭되는 보안 데이터 형이 아래와 같이 있습니다.
- 기본타입은 모두 8바이트 타입으로 캐스팅 되므로 int대신 long을, float 대신 double을 사용하는 등의 8바이트 타입 사용을 권장합니다.
기본 타입 | 보안 타입 | 기본 타입 | 보안 타입 |
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 |
사용 예제 C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// 아래 두 코드는 같은 동작을 하며 새로운 객체를 할당합니다. HerculesVar x = 100; HerculesVar y = new HerculesVar(100); int a = x; // 보안변수에서 일반변수로 값이 복사됩니다. y = 300; // y의 기존 객체가 해제되고 새로운 객체가 재 할당 됩니다. y.Set(300); // y의 값을 변경합니다. (y에 객체가 할당되어 있어야 하며 위의 경우보다 빠릅니다.) y = (int)x; // y가 x의 값으로 재할당 되어 서로 다른 객체를 참조합니다. y = x; // 주의: y는 x를 참조하게 됩니다. Set함수를 사용하면 두 값이 모두 바뀝니다. // unsigned 타입의 보안변수에 직접 연산할 때 빌드 에러가 발생하는 경우 // 명시적 캐스팅 또는 상수 뒤에 U를 명시해야 합니다. (1U 또는 (uint)1 의 형태로) // 자주 갱신되는 값인 경우 obj.Set(v); 형태로 사용하는 것이 성능 향상에 유리합니다. // 문자열은 아래와 같이 사용할 수 있습니다. 메모리상의 문자열만 보호가 됩니다. // “TEST” 형태의 정적 문자열을 대입하는 경우 원본 문자열이 코드에 노출될 수 있습니다. HerculesString securityString = <서버에서 내려받거나 동적으로 생성된 문자열 값>; string plainString = securityString; |
iOS, Android
- C의 경우는 변수의 값을 저장하거나 읽을 때 마다 API를 직접 호출해야 하므로 C++ 사용을 권장합니다. C++에는 템플릿 클래스가 정의되어 있습니다.
- 가급적이면 보안 변수를 전역 변수로 사용, 혹은 너무 잦은 할당과 해제가 이루어 지지 않는 곳에 위치시킨 후 사용하는 것이 좋습니다.
- #include 구문을 extern “C” 블럭 안에 넣으면 안 됩니다.
- Hive SDK가 초기화 된 이후에 사용해야 합니다.
사용 예제1. C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
#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 localSecurityString1 = <내려받거나 동적으로 생성한 문자열>; // 문자열로 초기화 CHerculesString localSecurityString2 = *g_securityString; // CHerculesString 객체로 초기화 std::string localString = *g_securityString; // CHerculesString 을 std::string 으로 localSecurityString2 = localSecurityString1; // CHerculesString 을 CHerculesString 으로 localSecurityString1 = localString.c_str(); // std::string 을 CHerculesString 으로 } |
사용 예제 C Language
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include "Hercules.h" HERCULES g_x; HERCULES g_y; HERCULES g_str; void callback(int error, const char *message) { // puts("Detected !"); } void StartApp() { // 보안 변수를 만듭니다. // 기본 타입과 구조체 변수를 넣어 사용할 수 있습니다. int var = 0; g_x = HerculesAddVar(&var, sizeof(var)); g_y = HerculesAddVar(&var, sizeof(var)); // “TEST” 형태의 정적 문자열을 대입하는 경우 원본 문자열이 코드에 노출될 수 있습니다. g_str = HerculesAddVar(<서버에서 내려받거나 동적으로 생성된 문자열>); } 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++은 연산자 오버로딩이 되어 있습니다.)
- 권장하는 방법
1 2 3 4 5 6 7 8 9 |
// 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; |
- 권장하지 않는 방법(잦은 접근)
1 2 3 4 5 6 |
// CHercules *securityVar = ... int values[5] = {5, 4, 6, 8, 11}; for(int i = 0; i < 5; i++) *securityVar += values[i]; |