port 2D step 5a: EterPack/EterPackManager + EterBase file units against the real 40250 packs
- Mirror copies: EterPack (EterPack, EterPackManager, EterPackCursor, CSHybridCrypt policy, Inline.h) and EterBase logic units tea/lzo/Timer/Stl/Random, with PORT-tagged width fixes (LONG index fields, static_assert(sizeof(TEterPackIndex) == 192), tea_word = Win32 unsigned long). - TEA pack keys are extracted from the reference EterPack.cpp at configure time into build/.../EterPackKeys.generated.h; nothing key-bearing is tracked. - Platform EterBase: FileBase (stdio, case-insensitive fallback), MappedFile (mmap / MapViewOfFile), CRC32, Debug, Utils StringPath/StringLowers. - Win32Crt: CreateDirectory/DeleteFile/_access/MAKEFOURCC; Win32MinMax.h min/max (force-included on MinGW, whose windows.h omits them in C++). - tests/port_eterpack_test: registers pack/Index like PackInitialize and checks 119 registrations / 103 packs + root / 54891 entries / 52609 paths / 2282 overrides with first-registered-wins, and that exactly the 4 short-layout SECURITY files fail to load. - 2R count corrected (136 -> 119 registrations, 103 distinct packs + root). Not runtime-reachable yet (asset_io pack backend is step 5b), so port-map statuses stay TODO. port_gate: macos/android/ios/windows PASS. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ namespace eterpack
|
||||
const DWORD c_IndexCC = MAKEFOURCC('E', 'P', 'K', 'D');
|
||||
const DWORD c_Version = 2;
|
||||
// FourCC + Version + m_indexCount
|
||||
const DWORD c_HeaderSize = sizeof(DWORD) + sizeof(DWORD) + sizeof(long);
|
||||
const DWORD c_HeaderSize = sizeof(DWORD) + sizeof(DWORD) + sizeof(LONG); // PORT: LONG (32-bit) for Win32 long
|
||||
};
|
||||
|
||||
enum EEterPackTypes
|
||||
@@ -46,20 +46,21 @@ enum EEterPackTypes
|
||||
#pragma pack(push, 4)
|
||||
typedef struct SEterPackIndex
|
||||
{
|
||||
long id;
|
||||
LONG id; // PORT: fixed-width Win32 long
|
||||
char filename[FILENAME_MAX_LEN + 1];
|
||||
DWORD filename_crc;
|
||||
long real_data_size;
|
||||
long data_size;
|
||||
LONG real_data_size; // PORT: fixed-width Win32 long
|
||||
LONG data_size; // PORT: fixed-width Win32 long
|
||||
#ifdef CHECKSUM_CHECK_MD5
|
||||
BYTE MD5Digest[16];
|
||||
#else
|
||||
DWORD data_crc;
|
||||
#endif
|
||||
long data_position;
|
||||
LONG data_position; // PORT: fixed-width Win32 long
|
||||
char compressed_type;
|
||||
} TEterPackIndex;
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(TEterPackIndex) == 192, "TEterPackIndex on-disk layout"); // PORT: on-disk struct
|
||||
|
||||
typedef std::unordered_map<DWORD, TEterPackIndex *> TDataPositionMap;
|
||||
typedef std::list<TEterPackIndex *> TFreeIndexList;
|
||||
@@ -170,7 +171,7 @@ class CEterPack
|
||||
char* m_file_data;
|
||||
unsigned m_file_size;
|
||||
|
||||
long m_indexCount;
|
||||
LONG m_indexCount; // PORT: read as 32-bit from the index header
|
||||
bool m_bEncrypted;
|
||||
|
||||
char m_dbName[DBNAME_MAX_LEN+1];
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include "StdAfx.h"
|
||||
#include "EterPackCursor.h"
|
||||
#include "Inline.h"
|
||||
|
||||
CEterPackCursor::CEterPackCursor(CEterPack* pack) : m_pPack(pack), m_pData(NULL), m_ReadPoint(0)
|
||||
{
|
||||
}
|
||||
|
||||
CEterPackCursor::~CEterPackCursor()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
bool CEterPackCursor::Open(const char* filename)
|
||||
{
|
||||
assert(m_pPack != NULL);
|
||||
|
||||
char tmpFilename[MAX_PATH + 1];
|
||||
strncpy(tmpFilename, filename, MAX_PATH);
|
||||
inlineConvertPackFilename(tmpFilename);
|
||||
|
||||
if (!m_pPack->Get(m_file, tmpFilename, &m_pData))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEterPackCursor::Close()
|
||||
{
|
||||
m_file.Destroy();
|
||||
m_pData = NULL;
|
||||
m_ReadPoint = 0;
|
||||
}
|
||||
|
||||
void CEterPackCursor::Seek(long offset)
|
||||
{
|
||||
m_ReadPoint = max(0, min(Size(), offset));
|
||||
}
|
||||
|
||||
bool CEterPackCursor::Read(LPVOID data, long size)
|
||||
{
|
||||
if (m_file.IsNull())
|
||||
return false;
|
||||
|
||||
if (m_ReadPoint + size > Size())
|
||||
return false;
|
||||
|
||||
memcpy(data, (char*) m_pData + m_ReadPoint, size);
|
||||
m_ReadPoint += size;
|
||||
return true;
|
||||
}
|
||||
|
||||
long CEterPackCursor::Size()
|
||||
{
|
||||
if (m_file.IsNull())
|
||||
return 0;
|
||||
|
||||
return m_file.Size();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef __INC_ETERPACKCURSOR_H__
|
||||
#define __INC_ETERPACKCURSOR_H__
|
||||
|
||||
#include "EterPack.h"
|
||||
|
||||
class CEterPackCursor
|
||||
{
|
||||
public:
|
||||
CEterPackCursor(CEterPack * pack);
|
||||
~CEterPackCursor();
|
||||
|
||||
bool Open(const char* filename);
|
||||
void Close();
|
||||
void Seek(long offset);
|
||||
bool Read(LPVOID data, long size);
|
||||
long Size();
|
||||
|
||||
private:
|
||||
CEterPack * m_pPack;
|
||||
CMappedFile m_file;
|
||||
LPCVOID m_pData;
|
||||
long m_ReadPoint;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,621 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <io.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "EterPackManager.h"
|
||||
#include "EterPackPolicy_CSHybridCrypt.h"
|
||||
|
||||
#include "../EterBase/Debug.h"
|
||||
#include "../EterBase/CRC32.h"
|
||||
|
||||
#define PATH_ABSOLUTE_YMIRWORK1 "d:/ymir work/"
|
||||
#define PATH_ABSOLUTE_YMIRWORK2 "d:\\ymir work\\"
|
||||
|
||||
#ifdef __THEMIDA__
|
||||
#include <ThemidaSDK.h>
|
||||
#endif
|
||||
|
||||
|
||||
CEterPack* CEterPackManager::FindPack(const char* c_szPathName)
|
||||
{
|
||||
std::string strFileName;
|
||||
|
||||
if (0 == ConvertFileName(c_szPathName, strFileName))
|
||||
{
|
||||
return &m_RootPack;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (TEterPackMap::iterator itor = m_DirPackMap.begin(); itor != m_DirPackMap.end(); ++itor)
|
||||
{
|
||||
const std::string & c_rstrName = itor->first;
|
||||
CEterPack * pEterPack = itor->second;
|
||||
|
||||
if (CompareName(c_rstrName.c_str(), c_rstrName.length(), strFileName.c_str()))
|
||||
{
|
||||
return pEterPack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CEterPackManager::SetCacheMode()
|
||||
{
|
||||
m_isCacheMode=true;
|
||||
}
|
||||
|
||||
void CEterPackManager::SetRelativePathMode()
|
||||
{
|
||||
m_bTryRelativePath = true;
|
||||
}
|
||||
|
||||
|
||||
// StringPath std::string 버전
|
||||
int CEterPackManager::ConvertFileName(const char * c_szFileName, std::string & rstrFileName)
|
||||
{
|
||||
rstrFileName = c_szFileName;
|
||||
stl_lowers(rstrFileName);
|
||||
|
||||
int iCount = 0;
|
||||
|
||||
for (DWORD i = 0; i < rstrFileName.length(); ++i)
|
||||
{
|
||||
if (rstrFileName[i] == '/')
|
||||
++iCount;
|
||||
else if (rstrFileName[i] == '\\')
|
||||
{
|
||||
rstrFileName[i] = '/';
|
||||
++iCount;
|
||||
}
|
||||
}
|
||||
|
||||
return iCount;
|
||||
}
|
||||
|
||||
bool CEterPackManager::CompareName(const char * c_szDirectoryName, DWORD /*dwLength*/, const char * c_szFileName)
|
||||
{
|
||||
const char * c_pszSrc = c_szDirectoryName;
|
||||
const char * c_pszCmp = c_szFileName;
|
||||
|
||||
while (*c_pszSrc)
|
||||
{
|
||||
if (*(c_pszSrc++) != *(c_pszCmp++))
|
||||
return false;
|
||||
|
||||
if (!*c_pszCmp)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEterPackManager::LoadStaticCache(const char* c_szFileName)
|
||||
{
|
||||
if (!m_isCacheMode)
|
||||
return;
|
||||
|
||||
std::string strFileName;
|
||||
if (0 == ConvertFileName(c_szFileName, strFileName))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD dwFileNameHash = GetCRC32(strFileName.c_str(), strFileName.length());
|
||||
|
||||
std::unordered_map<DWORD, SCache>::iterator f = m_kMap_dwNameKey_kCache.find(dwFileNameHash);
|
||||
if (m_kMap_dwNameKey_kCache.end() != f)
|
||||
return;
|
||||
|
||||
CMappedFile kMapFile;
|
||||
const void* c_pvData;
|
||||
if (!Get(kMapFile, c_szFileName, &c_pvData))
|
||||
return;
|
||||
|
||||
SCache kNewCache;
|
||||
kNewCache.m_dwBufSize = kMapFile.Size();
|
||||
kNewCache.m_abBufData = new BYTE[kNewCache.m_dwBufSize];
|
||||
memcpy(kNewCache.m_abBufData, c_pvData, kNewCache.m_dwBufSize);
|
||||
m_kMap_dwNameKey_kCache.insert(std::unordered_map<DWORD, SCache>::value_type(dwFileNameHash, kNewCache));
|
||||
}
|
||||
|
||||
CEterPackManager::SCache* CEterPackManager::__FindCache(DWORD dwFileNameHash)
|
||||
{
|
||||
std::unordered_map<DWORD, SCache>::iterator f=m_kMap_dwNameKey_kCache.find(dwFileNameHash);
|
||||
if (m_kMap_dwNameKey_kCache.end()==f)
|
||||
return NULL;
|
||||
|
||||
return &f->second;
|
||||
}
|
||||
|
||||
void CEterPackManager::__ClearCacheMap()
|
||||
{
|
||||
std::unordered_map<DWORD, SCache>::iterator i;
|
||||
|
||||
for (i = m_kMap_dwNameKey_kCache.begin(); i != m_kMap_dwNameKey_kCache.end(); ++i)
|
||||
delete [] i->second.m_abBufData;
|
||||
|
||||
m_kMap_dwNameKey_kCache.clear();
|
||||
}
|
||||
|
||||
struct TimeChecker
|
||||
{
|
||||
TimeChecker(const char* name) : name(name)
|
||||
{
|
||||
baseTime = timeGetTime();
|
||||
}
|
||||
~TimeChecker()
|
||||
{
|
||||
printf("load %s (%d)\n", name, timeGetTime() - baseTime);
|
||||
}
|
||||
|
||||
const char* name;
|
||||
DWORD baseTime;
|
||||
};
|
||||
|
||||
bool CEterPackManager::Get(CMappedFile & rMappedFile, const char * c_szFileName, LPCVOID * pData)
|
||||
{
|
||||
//TimeChecker timeChecker(c_szFileName);
|
||||
//Logf(1, "Load %s\n", c_szFileName);
|
||||
|
||||
if (m_iSearchMode == SEARCH_FILE_FIRST)
|
||||
{
|
||||
if (GetFromFile(rMappedFile, c_szFileName, pData))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return GetFromPack(rMappedFile, c_szFileName, pData);
|
||||
}
|
||||
|
||||
if (GetFromPack(rMappedFile, c_szFileName, pData))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return GetFromFile(rMappedFile, c_szFileName, pData);
|
||||
}
|
||||
|
||||
struct FinderLock
|
||||
{
|
||||
FinderLock(CRITICAL_SECTION& cs) : p_cs(&cs)
|
||||
{
|
||||
EnterCriticalSection(p_cs);
|
||||
}
|
||||
|
||||
~FinderLock()
|
||||
{
|
||||
LeaveCriticalSection(p_cs);
|
||||
}
|
||||
|
||||
CRITICAL_SECTION* p_cs;
|
||||
};
|
||||
|
||||
bool CEterPackManager::GetFromPack(CMappedFile & rMappedFile, const char * c_szFileName, LPCVOID * pData)
|
||||
{
|
||||
FinderLock lock(m_csFinder);
|
||||
|
||||
static std::string strFileName;
|
||||
|
||||
if (0 == ConvertFileName(c_szFileName, strFileName))
|
||||
{
|
||||
return m_RootPack.Get(rMappedFile, strFileName.c_str(), pData);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwFileNameHash = GetCRC32(strFileName.c_str(), strFileName.length());
|
||||
SCache* pkCache = __FindCache(dwFileNameHash);
|
||||
|
||||
if (pkCache)
|
||||
{
|
||||
rMappedFile.Link(pkCache->m_dwBufSize, pkCache->m_abBufData);
|
||||
return true;
|
||||
}
|
||||
|
||||
CEterFileDict::Item* pkFileItem = m_FileDict.GetItem(dwFileNameHash, strFileName.c_str());
|
||||
|
||||
if (pkFileItem)
|
||||
if (pkFileItem->pkPack)
|
||||
{
|
||||
bool r = pkFileItem->pkPack->Get2(rMappedFile, strFileName.c_str(), pkFileItem->pkInfo, pData);
|
||||
//pkFileItem->pkPack->ClearDataMemoryMap();
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
TraceError("CANNOT_FIND_PACK_FILE [%s]", strFileName.c_str());
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const time_t g_tCachingInterval = 10; // 10초
|
||||
void CEterPackManager::ArrangeMemoryMappedPack()
|
||||
{
|
||||
//time_t curTime = time(NULL);
|
||||
//CEterFileDict::TDict dict = m_FileDict.GetDict();
|
||||
//for (CEterFileDict::TDict::iterator it = dict.begin(); it != dict.end(); ++it)
|
||||
//{
|
||||
// CEterFileDict::Item &rFileItem = it->second;
|
||||
// CEterPack* pkPack = rFileItem.pkPack;
|
||||
// if (pkPack)
|
||||
// {
|
||||
// if (curTime - pkPack->GetLastAccessTime() > g_tCachingInterval)
|
||||
// {
|
||||
// pkPack->ClearDataMemoryMap();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
bool CEterPackManager::GetFromFile(CMappedFile & rMappedFile, const char * c_szFileName, LPCVOID * pData)
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
//const char *pcExt = strchr(c_szFileName, '.');
|
||||
//if (pcExt &&
|
||||
// _strnicmp(pcExt, ".py", 3) == 0 && // python 스크립트 중
|
||||
// stricmp(c_szFileName, "logininfo.py") != 0 && // 로그인 정보 파일이 아니고
|
||||
// strnicmp(c_szFileName, "locale", 6) != 0
|
||||
// )
|
||||
//{
|
||||
// return false;
|
||||
//}
|
||||
#endif
|
||||
|
||||
//if(m_bTryRelativePath) {
|
||||
// if (strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK1, strlen(PATH_ABSOLUTE_YMIRWORK1)) == 0 || strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK2, strlen(PATH_ABSOLUTE_YMIRWORK2)) == 0) {
|
||||
// if(rMappedFile.Create(c_szFileName+strlen(PATH_ABSOLUTE_YMIRWORK1), pData, 0, 0))
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
return rMappedFile.Create(c_szFileName, pData, 0, 0) ? true : false;
|
||||
}
|
||||
|
||||
bool CEterPackManager::isExistInPack(const char * c_szFileName)
|
||||
{
|
||||
std::string strFileName;
|
||||
|
||||
if (0 == ConvertFileName(c_szFileName, strFileName))
|
||||
{
|
||||
return m_RootPack.IsExist(strFileName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dwFileNameHash = GetCRC32(strFileName.c_str(), strFileName.length());
|
||||
CEterFileDict::Item* pkFileItem = m_FileDict.GetItem(dwFileNameHash, strFileName.c_str());
|
||||
|
||||
if (pkFileItem)
|
||||
if (pkFileItem->pkPack)
|
||||
return pkFileItem->pkPack->IsExist(strFileName.c_str());
|
||||
}
|
||||
|
||||
// NOTE : 매치 되는 팩이 없다면 false - [levites]
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CEterPackManager::isExist(const char * c_szFileName)
|
||||
{
|
||||
if (m_iSearchMode == SEARCH_PACK_FIRST)
|
||||
{
|
||||
if (isExistInPack(c_szFileName))
|
||||
return true;
|
||||
|
||||
return _access(c_szFileName, 0) == 0 ? true : false;
|
||||
}
|
||||
|
||||
//if(m_bTryRelativePath) {
|
||||
// if (strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK1, strlen(PATH_ABSOLUTE_YMIRWORK1)) == 0 || strnicmp(c_szFileName, PATH_ABSOLUTE_YMIRWORK2, strlen(PATH_ABSOLUTE_YMIRWORK2)) == 0) {
|
||||
// if(access(c_szFileName+strlen(PATH_ABSOLUTE_YMIRWORK1), 0) == 0)
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (_access(c_szFileName, 0) == 0)
|
||||
return true;
|
||||
|
||||
return isExistInPack(c_szFileName);
|
||||
}
|
||||
|
||||
|
||||
void CEterPackManager::RegisterRootPack(const char * c_szName)
|
||||
{
|
||||
if (!m_RootPack.Create(m_FileDict, c_szName, ""))
|
||||
{
|
||||
TraceError("%s: Pack file does not exist", c_szName);
|
||||
}
|
||||
}
|
||||
|
||||
const char * CEterPackManager::GetRootPackFileName()
|
||||
{
|
||||
return m_RootPack.GetDBName();
|
||||
}
|
||||
|
||||
bool CEterPackManager::DecryptPackIV(DWORD dwPanamaKey)
|
||||
{
|
||||
TEterPackMap::iterator itor = m_PackMap.begin();
|
||||
while (itor != m_PackMap.end())
|
||||
{
|
||||
itor->second->DecryptIV(dwPanamaKey);
|
||||
itor++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEterPackManager::RegisterPackWhenPackMaking(const char * c_szName, const char * c_szDirectory, CEterPack* pPack)
|
||||
{
|
||||
m_PackMap.insert(TEterPackMap::value_type(c_szName, pPack));
|
||||
m_PackList.push_front(pPack);
|
||||
|
||||
m_DirPackMap.insert(TEterPackMap::value_type(c_szDirectory, pPack));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CEterPackManager::RegisterPack(const char * c_szName, const char * c_szDirectory, const BYTE* c_pbIV)
|
||||
{
|
||||
CEterPack * pEterPack = NULL;
|
||||
{
|
||||
TEterPackMap::iterator itor = m_PackMap.find(c_szName);
|
||||
|
||||
if (m_PackMap.end() == itor)
|
||||
{
|
||||
bool bReadOnly = true;
|
||||
|
||||
pEterPack = new CEterPack;
|
||||
if (pEterPack->Create(m_FileDict, c_szName, c_szDirectory, bReadOnly, c_pbIV))
|
||||
{
|
||||
m_PackMap.insert(TEterPackMap::value_type(c_szName, pEterPack));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
Tracef("The eterpack doesn't exist [%s]\n", c_szName);
|
||||
#endif
|
||||
delete pEterPack;
|
||||
pEterPack = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pEterPack = itor->second;
|
||||
}
|
||||
}
|
||||
|
||||
if (c_szDirectory && c_szDirectory[0] != '*')
|
||||
{
|
||||
TEterPackMap::iterator itor = m_DirPackMap.find(c_szDirectory);
|
||||
if (m_DirPackMap.end() == itor)
|
||||
{
|
||||
m_PackList.push_front(pEterPack);
|
||||
m_DirPackMap.insert(TEterPackMap::value_type(c_szDirectory, pEterPack));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEterPackManager::SetSearchMode(bool bPackFirst)
|
||||
{
|
||||
m_iSearchMode = bPackFirst ? SEARCH_PACK_FIRST : SEARCH_FILE_FIRST;
|
||||
}
|
||||
|
||||
int CEterPackManager::GetSearchMode()
|
||||
{
|
||||
return m_iSearchMode;
|
||||
}
|
||||
|
||||
CEterPackManager::CEterPackManager() : m_bTryRelativePath(false), m_iSearchMode(SEARCH_FILE_FIRST), m_isCacheMode(false)
|
||||
{
|
||||
InitializeCriticalSection(&m_csFinder);
|
||||
}
|
||||
|
||||
CEterPackManager::~CEterPackManager()
|
||||
{
|
||||
__ClearCacheMap();
|
||||
|
||||
TEterPackMap::iterator i = m_PackMap.begin();
|
||||
TEterPackMap::iterator e = m_PackMap.end();
|
||||
while (i != e)
|
||||
{
|
||||
delete i->second;
|
||||
i++;
|
||||
}
|
||||
DeleteCriticalSection(&m_csFinder);
|
||||
}
|
||||
|
||||
void CEterPackManager::RetrieveHybridCryptPackKeys(const BYTE *pStream)
|
||||
{
|
||||
////dump file format
|
||||
//total packagecnt (4byte)
|
||||
// for packagecntpackage
|
||||
// db name hash ( stl.h stringhash )
|
||||
// extension cnt( 4byte)
|
||||
// for extension cnt
|
||||
// ext hash ( stl.h stringhash )
|
||||
// key-16byte
|
||||
// iv-16byte
|
||||
int iMemOffset = 0;
|
||||
|
||||
int iPackageCnt;
|
||||
DWORD dwPackageNameHash;
|
||||
|
||||
memcpy( &iPackageCnt, pStream + iMemOffset, sizeof(int) );
|
||||
iMemOffset += sizeof(iPackageCnt);
|
||||
|
||||
for( int i = 0; i < iPackageCnt; ++i )
|
||||
{
|
||||
int iRecvedCryptKeySize = 0;
|
||||
memcpy( &iRecvedCryptKeySize, pStream + iMemOffset, sizeof(iRecvedCryptKeySize) );
|
||||
iRecvedCryptKeySize -= sizeof(dwPackageNameHash); // 서버에서 받은 key stream에는 filename hash가 포함되어 있으므로, hash 사이즈 만큼 배줌.
|
||||
iMemOffset += sizeof(iRecvedCryptKeySize);
|
||||
|
||||
memcpy( &dwPackageNameHash, pStream + iMemOffset, sizeof(dwPackageNameHash) );
|
||||
iMemOffset += sizeof(dwPackageNameHash);
|
||||
|
||||
TEterPackMap::const_iterator cit;
|
||||
for( cit = m_PackMap.begin(); cit != m_PackMap.end(); ++cit )
|
||||
{
|
||||
auto ssvv = std::string(cit->first);
|
||||
std::string noPathName = CFileNameHelper::NoPath(ssvv);
|
||||
if( dwPackageNameHash == stringhash().GetHash(noPathName) )
|
||||
{
|
||||
EterPackPolicy_CSHybridCrypt* pCryptPolicy = cit->second->GetPackPolicy_HybridCrypt();
|
||||
int iHavedCryptKeySize = pCryptPolicy->ReadCryptKeyInfoFromStream( pStream + iMemOffset );
|
||||
if (iRecvedCryptKeySize != iHavedCryptKeySize)
|
||||
{
|
||||
TraceError("CEterPackManager::RetrieveHybridCryptPackKeys cryptokey length of file(%s) is not matched. received(%d) != haved(%d)", noPathName.c_str(), iRecvedCryptKeySize, iHavedCryptKeySize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
iMemOffset += iRecvedCryptKeySize;
|
||||
}
|
||||
}
|
||||
|
||||
void CEterPackManager::RetrieveHybridCryptPackSDB( const BYTE* pStream )
|
||||
{
|
||||
//cnt
|
||||
//for cnt
|
||||
//DWORD dwPackageIdentifier;
|
||||
//DWORD dwFileIdentifier;
|
||||
//std::vector<BYTE> vecSDBStream;
|
||||
int iReadOffset = 0;
|
||||
int iSDBInfoCount = 0;
|
||||
|
||||
memcpy( &iSDBInfoCount, pStream+iReadOffset, sizeof(int) );
|
||||
iReadOffset += sizeof(int);
|
||||
|
||||
for( int i = 0; i < iSDBInfoCount; ++i )
|
||||
{
|
||||
DWORD dwPackgeIdentifier;
|
||||
memcpy( &dwPackgeIdentifier, pStream+iReadOffset, sizeof(DWORD) );
|
||||
iReadOffset += sizeof(DWORD);
|
||||
|
||||
TEterPackMap::const_iterator cit;
|
||||
for( cit = m_PackMap.begin(); cit != m_PackMap.end(); ++cit )
|
||||
{
|
||||
auto ssvv = std::string(cit->first);
|
||||
std::string noPathName = CFileNameHelper::NoPath(ssvv);
|
||||
if( dwPackgeIdentifier == stringhash().GetHash(noPathName) )
|
||||
{
|
||||
EterPackPolicy_CSHybridCrypt* pCryptPolicy = cit->second->GetPackPolicy_HybridCrypt();
|
||||
iReadOffset += pCryptPolicy->ReadSupplementatyDataBlockFromStream( pStream+iReadOffset );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CEterPackManager::WriteHybridCryptPackInfo(const char* pFileName)
|
||||
{
|
||||
//NOTE : this file format contains a little bit of redundant data.
|
||||
//however it`s better for seperating cryptkey & supplementary data block.
|
||||
|
||||
//dump file format
|
||||
|
||||
//SDB data offset(4)
|
||||
|
||||
// about cryptkey
|
||||
//total packagecnt (4byte)
|
||||
// for packagecnt
|
||||
// db name hash 4byte( stl.h stringhash )
|
||||
// extension cnt( 4byte)
|
||||
// for extension cnt
|
||||
// ext hash ( stl.h stringhash )
|
||||
// key-16byte
|
||||
// iv-16byte
|
||||
|
||||
//about SDB data
|
||||
//total packagecnt (4byte)
|
||||
// for packagecnt
|
||||
// db name hash 4byte( stl.h stringhash ) +child node size(4byte)
|
||||
// sdb file cnt( 4byte )
|
||||
// for sdb file cnt
|
||||
// filename hash ( stl.h stringhash )
|
||||
// related map name size(4), relate map name
|
||||
// sdb block size( 1byte )
|
||||
// sdb blocks
|
||||
|
||||
CFileBase keyFile;
|
||||
|
||||
if( !keyFile.Create( pFileName, CFileBase::FILEMODE_WRITE) )
|
||||
{
|
||||
//TODO : write log
|
||||
return;
|
||||
}
|
||||
|
||||
int iKeyPackageCount = 0;
|
||||
|
||||
//write later ( SDB Offset & PackageCnt for Key )
|
||||
keyFile.SeekCur(2*sizeof(int));
|
||||
|
||||
TEterPackMap::const_iterator cit;
|
||||
for( cit = m_PackMap.begin(); cit != m_PackMap.end(); ++cit )
|
||||
{
|
||||
EterPackPolicy_CSHybridCrypt* pPolicy = cit->second->GetPackPolicy_HybridCrypt();
|
||||
if( !pPolicy || !pPolicy->IsContainingCryptKey() )
|
||||
continue;
|
||||
|
||||
iKeyPackageCount++;
|
||||
auto ssvv = std::string(cit->first);
|
||||
std::string noPathName = CFileNameHelper::NoPath(ssvv);
|
||||
|
||||
DWORD dwPackNamehash = stringhash().GetHash(noPathName);
|
||||
|
||||
CMakePackLog::GetSingleton().Writef("CEterPackManager::WriteHybridCryptPackInfo PackName : %s, Hash : %x", noPathName.c_str(), dwPackNamehash);
|
||||
keyFile.Write( &dwPackNamehash, sizeof(DWORD) );
|
||||
|
||||
pPolicy->WriteCryptKeyToFile( keyFile );
|
||||
}
|
||||
|
||||
//Write SDB Data
|
||||
int iSDBDataOffset = keyFile.GetPosition();
|
||||
int iSDBPackageCnt = 0;
|
||||
|
||||
//Write SDB PackageCnt Later
|
||||
keyFile.SeekCur(sizeof(int));
|
||||
for( cit = m_PackMap.begin(); cit != m_PackMap.end(); ++cit )
|
||||
{
|
||||
EterPackPolicy_CSHybridCrypt* pPolicy = cit->second->GetPackPolicy_HybridCrypt();
|
||||
if( !pPolicy || !pPolicy->IsContainingSDBFile() )
|
||||
continue;
|
||||
|
||||
iSDBPackageCnt++;
|
||||
|
||||
auto ssvv1 = std::string(cit->first);
|
||||
auto noPathName = CFileNameHelper::NoPath(ssvv1);
|
||||
|
||||
DWORD dwPackNamehash = stringhash().GetHash(noPathName);
|
||||
keyFile.Write( &dwPackNamehash, sizeof(DWORD) );
|
||||
|
||||
int iSDBSizeWriteOffset = keyFile.GetPosition();
|
||||
keyFile.SeekCur(sizeof(int));
|
||||
|
||||
pPolicy->WriteSupplementaryDataBlockToFile( keyFile );
|
||||
int iSDBSizeAfterWrite = keyFile.GetPosition();
|
||||
|
||||
keyFile.Seek(iSDBSizeWriteOffset);
|
||||
|
||||
int iSDBSize = iSDBSizeAfterWrite-(iSDBSizeWriteOffset+4);
|
||||
keyFile.Write( &iSDBSize, sizeof(int) );
|
||||
|
||||
keyFile.Seek(iSDBSizeAfterWrite);
|
||||
}
|
||||
|
||||
//write sdb data start offset & package cnt
|
||||
keyFile.Seek(0);
|
||||
keyFile.Write( &iSDBDataOffset, sizeof(int));
|
||||
keyFile.Write( &iKeyPackageCount, sizeof(int));
|
||||
|
||||
keyFile.Seek(iSDBDataOffset);
|
||||
keyFile.Write( &iSDBPackageCnt, sizeof(int));
|
||||
|
||||
keyFile.Close();
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
#include "StdAfx.h"
|
||||
#include "EterPackPolicy_CSHybridCrypt.h"
|
||||
#include "../EterBase/Stl.h"
|
||||
#include "../EterBase/Filename.h"
|
||||
#include "../EterBase/FileBase.h"
|
||||
#include "../EterBase/CRC32.h"
|
||||
#include "../EterBase/lzo.h"
|
||||
#include "../EterBase/Random.h"
|
||||
#include <cryptopp/modes.h>
|
||||
#include <cryptopp/osrng.h>
|
||||
|
||||
using namespace CryptoPP;
|
||||
|
||||
#define CIPHER_MODE CTR_Mode
|
||||
|
||||
#ifdef __THEMIDA__
|
||||
#include <ThemidaSDK.h>
|
||||
#endif
|
||||
//Cipher
|
||||
//Block Size
|
||||
//Key Length
|
||||
//
|
||||
//Default Minimum Maximum
|
||||
//AES(Rijndael) 16 16 16 32
|
||||
//Blowfish 8 16 0 56
|
||||
//Camellia 16 16 16 32
|
||||
//CAST-128 8 16 5 16
|
||||
//CAST-256 16 16 16 32
|
||||
//DES 8 8 8 8
|
||||
//DES-EDE2 8 16 16 16
|
||||
//DES-EDE3 8 24 24 24
|
||||
//DES-XEX3 8 24 24 24
|
||||
//GOST 8 32 32 32
|
||||
//IDEA 8 16 16 16
|
||||
//MARS 16 16 16 56
|
||||
//RC2 8 16 1 128
|
||||
//RC5 8 16 0 255
|
||||
//RC6 16 16 0 255
|
||||
//SAFER-K 8 16 8 16
|
||||
//SAFER-SK 8 16 8 16
|
||||
//Serpent 16 16 1 32
|
||||
//SHACAL-2 32 16 1 64
|
||||
//SHARK-E 8 16 1 16
|
||||
//SKIPJACK 8 10 1 10
|
||||
//3-Way 12 12 1 12
|
||||
//Twofish 16 16 0 32
|
||||
//XTEA 8 16 1 16
|
||||
|
||||
inline std::string GetFileExt( std::string& rfileName )
|
||||
{
|
||||
stl_lowers(rfileName);
|
||||
return CFileNameHelper::GetExtension(rfileName);
|
||||
}
|
||||
|
||||
EterPackPolicy_CSHybridCrypt::~EterPackPolicy_CSHybridCrypt()
|
||||
{
|
||||
m_mapHybridCryptKey.clear();
|
||||
m_mapSDBMap.clear();
|
||||
}
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::IsContainingCryptKey() const
|
||||
{
|
||||
return (m_mapHybridCryptKey.size() > 0) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::GenerateCryptKey( std::string& rfileName )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
//make lower & extract ext
|
||||
std::string extName = GetFileExt(rfileName);
|
||||
stl_lowers(extName);
|
||||
|
||||
DWORD dwExtHash = stringhash().GetHash(extName);
|
||||
|
||||
TCSHybridCryptKeyMap::const_iterator cit = m_mapHybridCryptKey.find( dwExtHash );
|
||||
|
||||
if( cit != m_mapHybridCryptKey.end() )
|
||||
{
|
||||
//TODO : log already registered
|
||||
return false;
|
||||
}
|
||||
|
||||
static AutoSeededRandomPool rnd;
|
||||
|
||||
TCSHybridCryptKey info;
|
||||
{
|
||||
rnd.GenerateBlock( &(info.uEncryptKey.key[0]), sizeof(info.uEncryptKey) );
|
||||
rnd.GenerateBlock( &(info.uEncryptIV.iv[0]), sizeof(info.uEncryptIV) );
|
||||
|
||||
//for test
|
||||
/* memset( &info.uEncryptKey.key, 0x10, sizeof(info.uEncryptKey) );
|
||||
memset( &info.uEncryptIV.iv, 0x10, sizeof(info.uEncryptIV) ); */
|
||||
}
|
||||
m_mapHybridCryptKey[dwExtHash] = info;
|
||||
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::GetPerFileCryptKey( std::string& rfileName, eHybridCipherAlgorithm& eAlgorithm, TEncryptKey& key, TEncryptIV& iv )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
std::string fileNamelower = rfileName;
|
||||
stl_lowers(fileNamelower);
|
||||
|
||||
std::string extName = GetFileExt(fileNamelower);
|
||||
|
||||
TCSHybridCryptKeyMap::const_iterator cit = m_mapHybridCryptKey.find( stringhash().GetHash(extName));
|
||||
|
||||
if( cit == m_mapHybridCryptKey.end() )
|
||||
{
|
||||
//TODO : log no file ext info
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD dwfileNameCrc = GetCRC32(fileNamelower.c_str(), fileNamelower.size());
|
||||
|
||||
//make file specific algorithm & key & iv
|
||||
eAlgorithm = (eHybridCipherAlgorithm)(dwfileNameCrc % Num_Of_Ciphers);
|
||||
|
||||
::memcpy(key.key, cit->second.uEncryptKey.key, sizeof(key) );
|
||||
::memcpy(iv.iv, cit->second.uEncryptIV.iv, sizeof(iv) );
|
||||
|
||||
|
||||
//Themida Warning
|
||||
for( int i = 0; i < (sizeof(key)/sizeof(dwfileNameCrc)); ++i)
|
||||
{
|
||||
*((DWORD*)key.key + i) ^= dwfileNameCrc;
|
||||
}
|
||||
for( int i = 0; i < (sizeof(iv)/sizeof(dwfileNameCrc)); ++i)
|
||||
{
|
||||
*((DWORD*)iv.iv + i) ^= dwfileNameCrc;
|
||||
}
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::EncryptMemory( std::string& rfileName, IN const BYTE* pSrcData, IN int iSrcLen, OUT CLZObject& zObj )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
eHybridCipherAlgorithm eAlgorithm;
|
||||
TEncryptKey key;
|
||||
TEncryptIV iv;
|
||||
|
||||
if( !GetPerFileCryptKey( rfileName, eAlgorithm, key, iv ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// start cipher
|
||||
std::string strCipher;
|
||||
//NOTE : ciphered stream size could be different from original size if you choose diffrent cipher mode & algorithm
|
||||
//( i.e ECB or CBC mode )
|
||||
strCipher.reserve(iSrcLen);
|
||||
|
||||
if( eAlgorithm == e_Cipher_Camellia )
|
||||
{
|
||||
// Encryptor
|
||||
CIPHER_MODE<Camellia>::Encryption Encryptor;
|
||||
Encryptor.SetKeyWithIV(key.keyCamellia, sizeof(key.keyCamellia), iv.ivCamellia, sizeof(iv.ivCamellia));
|
||||
|
||||
ArraySource(pSrcData, iSrcLen, true,
|
||||
new StreamTransformationFilter(Encryptor, new CryptoPP::StringSink(strCipher)));
|
||||
}
|
||||
else if( eAlgorithm == e_Cipher_Twofish )
|
||||
{
|
||||
// Encryptor
|
||||
CIPHER_MODE<Twofish>::Encryption Encryptor;
|
||||
Encryptor.SetKeyWithIV(key.keyTwofish, sizeof(key.keyTwofish), iv.ivTwofish, sizeof(iv.ivTwofish));
|
||||
|
||||
ArraySource(pSrcData, iSrcLen, true,
|
||||
new StreamTransformationFilter(Encryptor, new CryptoPP::StringSink(strCipher)));
|
||||
}
|
||||
else if( eAlgorithm == e_Cipher_XTEA )
|
||||
{
|
||||
// Encryptor
|
||||
CIPHER_MODE<XTEA>::Encryption Encryptor;
|
||||
Encryptor.SetKeyWithIV(key.keyXTEA, sizeof(key.keyXTEA), iv.ivXTEA, sizeof(iv.ivXTEA));
|
||||
|
||||
ArraySource(pSrcData, iSrcLen, true,
|
||||
new StreamTransformationFilter(Encryptor, new CryptoPP::StringSink(strCipher)));
|
||||
}
|
||||
|
||||
if (strCipher.length() != iSrcLen)
|
||||
{
|
||||
//TODO: size error log
|
||||
return false;
|
||||
}
|
||||
|
||||
zObj.AllocBuffer(iSrcLen);
|
||||
memcpy(zObj.GetBuffer(), strCipher.c_str(), strCipher.length() );
|
||||
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::DecryptMemory( std::string& rfilename, IN const BYTE* pEncryptedData, IN int iEncryptedLen, OUT CLZObject& zObj )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
eHybridCipherAlgorithm eAlgorithm;
|
||||
TEncryptKey key;
|
||||
TEncryptIV iv;
|
||||
|
||||
if( !GetPerFileCryptKey( rfilename, eAlgorithm, key, iv ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// start decipher
|
||||
std::string strDecipher;
|
||||
//NOTE : ciphered stream size could be different from original size if you choose diffrent cipher mode & algorithm
|
||||
//( i.e ECB or CBC mode )
|
||||
strDecipher.reserve(iEncryptedLen);
|
||||
|
||||
if( eAlgorithm == e_Cipher_Camellia )
|
||||
{
|
||||
// Decryptor
|
||||
CIPHER_MODE<Camellia>::Decryption Decryptor;
|
||||
Decryptor.SetKeyWithIV(key.keyCamellia, sizeof(key.keyCamellia), iv.ivCamellia, sizeof(iv.ivCamellia));
|
||||
|
||||
ArraySource(pEncryptedData, iEncryptedLen, true,
|
||||
new StreamTransformationFilter(Decryptor, new CryptoPP::StringSink(strDecipher)));
|
||||
}
|
||||
else if( eAlgorithm == e_Cipher_Twofish )
|
||||
{
|
||||
// Decryptor
|
||||
CIPHER_MODE<Twofish>::Decryption Decryptor;
|
||||
Decryptor.SetKeyWithIV(key.keyTwofish, sizeof(key.keyTwofish), iv.ivTwofish, sizeof(iv.ivTwofish));
|
||||
|
||||
ArraySource(pEncryptedData, iEncryptedLen, true,
|
||||
new StreamTransformationFilter(Decryptor, new CryptoPP::StringSink(strDecipher)));
|
||||
}
|
||||
else if( eAlgorithm == e_Cipher_XTEA )
|
||||
{
|
||||
// Decryptor
|
||||
CIPHER_MODE<XTEA>::Decryption Decryptor;
|
||||
Decryptor.SetKeyWithIV(key.keyXTEA, sizeof(key.keyXTEA), iv.ivXTEA, sizeof(iv.ivXTEA));
|
||||
|
||||
ArraySource(pEncryptedData, iEncryptedLen, true,
|
||||
new StreamTransformationFilter(Decryptor, new CryptoPP::StringSink(strDecipher)));
|
||||
}
|
||||
|
||||
|
||||
if (strDecipher.length() != iEncryptedLen)
|
||||
{
|
||||
//TODO: size error log
|
||||
return false;
|
||||
}
|
||||
|
||||
zObj.AllocBuffer(iEncryptedLen);
|
||||
memcpy(zObj.GetBuffer(), strDecipher.c_str(), strDecipher.length() );
|
||||
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void EterPackPolicy_CSHybridCrypt::WriteCryptKeyToFile( CFileBase& rFile )
|
||||
{
|
||||
// ext cnt 4byte
|
||||
// for ext hash ( crc32 )
|
||||
// key-16byte
|
||||
// iv-16byte
|
||||
|
||||
DWORD dwCryptKeySize = m_mapHybridCryptKey.size();
|
||||
rFile.Write( &dwCryptKeySize, sizeof(DWORD) );
|
||||
|
||||
TCSHybridCryptKeyMap::const_iterator cit;
|
||||
for( cit = m_mapHybridCryptKey.begin(); cit != m_mapHybridCryptKey.end(); ++cit )
|
||||
{
|
||||
DWORD extNamehash = cit->first;
|
||||
const TCSHybridCryptKey& CryptKey = cit->second;
|
||||
|
||||
rFile.Write( &extNamehash, sizeof(DWORD) );
|
||||
rFile.Write( CryptKey.uEncryptKey.key, sizeof(TEncryptKey) );
|
||||
rFile.Write( CryptKey.uEncryptIV.iv, sizeof(TEncryptIV) );
|
||||
}
|
||||
}
|
||||
|
||||
int EterPackPolicy_CSHybridCrypt::ReadCryptKeyInfoFromStream( IN const BYTE* pStream )
|
||||
{
|
||||
int iStreamOffset = 0;
|
||||
|
||||
DWORD dwCryptoInfoSize;
|
||||
memcpy(&dwCryptoInfoSize, pStream, sizeof(DWORD) );
|
||||
iStreamOffset += sizeof(DWORD);
|
||||
|
||||
DWORD dwExtHash;
|
||||
|
||||
m_mapHybridCryptKey.clear();
|
||||
|
||||
for( int i = 0; i < dwCryptoInfoSize; ++i )
|
||||
{
|
||||
memcpy(&dwExtHash, pStream + iStreamOffset, sizeof(DWORD) );
|
||||
iStreamOffset += sizeof(DWORD);
|
||||
|
||||
TCSHybridCryptKey info;
|
||||
{
|
||||
memcpy(info.uEncryptKey.key, pStream + iStreamOffset, sizeof(TEncryptKey) );
|
||||
iStreamOffset += sizeof(TEncryptKey);
|
||||
|
||||
memcpy(info.uEncryptIV.iv, pStream + iStreamOffset, sizeof(TEncryptIV) );
|
||||
iStreamOffset += sizeof(TEncryptIV);
|
||||
}
|
||||
|
||||
m_mapHybridCryptKey[dwExtHash] = info;
|
||||
}
|
||||
|
||||
return iStreamOffset;
|
||||
}
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::GenerateSupplementaryDataBlock(std::string& rfilename, const std::string& strMapName, IN const BYTE* pSrcData, IN int iSrcLen, OUT LPBYTE& pDestData, OUT int& iDestLen )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
std::string fileNamelower = rfilename;
|
||||
stl_lowers( fileNamelower );
|
||||
|
||||
DWORD dwFileNameHash = stringhash().GetHash(fileNamelower);
|
||||
TSupplementaryDataBlockMap::const_iterator cit = m_mapSDBMap.find( dwFileNameHash );
|
||||
|
||||
if( cit != m_mapSDBMap.end() )
|
||||
{
|
||||
//TODO : log already registered
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO : Find Better Method for deciding SDB Postion & Size
|
||||
|
||||
//prevent stream copy duplication
|
||||
TSupplementaryDataBlockInfo info;
|
||||
m_mapSDBMap[dwFileNameHash] = info;
|
||||
|
||||
std::string& strRelatedMapName = m_mapSDBMap[dwFileNameHash].strRelatedMapName;
|
||||
std::vector<BYTE>& sdbVector = m_mapSDBMap[dwFileNameHash].vecStream;
|
||||
|
||||
|
||||
//fill the data!!
|
||||
{
|
||||
strRelatedMapName = strMapName;
|
||||
|
||||
int iSDBSize = random_range( 64, 128 );
|
||||
|
||||
if( iSrcLen < iSDBSize )
|
||||
{
|
||||
iSDBSize = iSrcLen - 1;
|
||||
if( iSDBSize <= 0 )
|
||||
{
|
||||
//TODO : is there 1byte file exist???
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sdbVector.resize( iSDBSize );
|
||||
|
||||
iDestLen = iSrcLen - iSDBSize;
|
||||
pDestData = (LPBYTE)pSrcData;
|
||||
|
||||
memcpy( &sdbVector[0], pDestData + iDestLen, iSDBSize );
|
||||
}
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::GetSupplementaryDataBlock( std::string& rfilename, OUT LPBYTE& pSDB, OUT int& iSDBSize )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
std::string fileNamelower = rfilename;
|
||||
stl_lowers( fileNamelower );
|
||||
|
||||
DWORD dwFileNameHash = stringhash().GetHash(fileNamelower);
|
||||
TSupplementaryDataBlockMap::const_iterator cit = m_mapSDBMap.find( dwFileNameHash );
|
||||
|
||||
if( cit == m_mapSDBMap.end() )
|
||||
{
|
||||
//TODO : log already registered
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<BYTE>& vecSDB = cit->second.vecStream;
|
||||
|
||||
iSDBSize = vecSDB.size();
|
||||
|
||||
if(iSDBSize <= 0)
|
||||
{
|
||||
pSDB = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
pSDB = (BYTE*)&vecSDB[0];
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EterPackPolicy_CSHybridCrypt::IsContainingSDBFile() const
|
||||
{
|
||||
return m_mapSDBMap.size() > 0 ? true : false;
|
||||
}
|
||||
|
||||
void EterPackPolicy_CSHybridCrypt::WriteSupplementaryDataBlockToFile( CFileBase& rFile )
|
||||
{
|
||||
//about SDB data
|
||||
// sdb file cnt( 4byte )
|
||||
// for sdb file cnt
|
||||
// filename hash ( stl.h stringhash )
|
||||
// related map name size(4), relate map name
|
||||
// sdb block size( 1byte )
|
||||
// sdb blocks
|
||||
|
||||
DWORD dwSDBMapSize = m_mapSDBMap.size();
|
||||
rFile.Write( &dwSDBMapSize, sizeof(DWORD) );
|
||||
|
||||
TSupplementaryDataBlockMap::const_iterator cit;
|
||||
for( cit = m_mapSDBMap.begin(); cit != m_mapSDBMap.end(); ++cit )
|
||||
{
|
||||
DWORD dwFileNamehash = cit->first;
|
||||
rFile.Write( &dwFileNamehash, sizeof(DWORD) );
|
||||
|
||||
const std::string strRelatedMapName = cit->second.strRelatedMapName;
|
||||
DWORD dwMapNameSize = strRelatedMapName.size();
|
||||
rFile.Write( &dwMapNameSize, sizeof(DWORD) );
|
||||
rFile.Write( strRelatedMapName.c_str(), dwMapNameSize );
|
||||
|
||||
const std::vector<BYTE>& sdbVector = cit->second.vecStream;
|
||||
BYTE bSDBSize = (BYTE)(sdbVector.size());
|
||||
|
||||
rFile.Write( &bSDBSize, sizeof(bSDBSize) );
|
||||
if( bSDBSize > 0 )
|
||||
rFile.Write( &sdbVector[0], bSDBSize );
|
||||
}
|
||||
}
|
||||
|
||||
int EterPackPolicy_CSHybridCrypt::ReadSupplementatyDataBlockFromStream( IN const BYTE* pStream )
|
||||
{
|
||||
#ifdef __THEMIDA__
|
||||
VM_START
|
||||
#endif
|
||||
|
||||
//DWORD dwFileIdentifier;
|
||||
//std::vector<BYTE> vecSDBStream;
|
||||
|
||||
DWORD dwFileNameHash;
|
||||
BYTE bSDBSize;
|
||||
int iStreamOffset = 0;
|
||||
|
||||
memcpy(&dwFileNameHash, pStream + iStreamOffset, sizeof(DWORD) );
|
||||
iStreamOffset += sizeof(DWORD);
|
||||
|
||||
memcpy(&bSDBSize, pStream + iStreamOffset, sizeof(BYTE) );
|
||||
iStreamOffset += sizeof(BYTE);
|
||||
|
||||
// NOTE : related map name isn`t required in client. so we don`t recv it from stream to reduce packet size.
|
||||
TSupplementaryDataBlockInfo info;
|
||||
{
|
||||
info.vecStream.resize( bSDBSize );
|
||||
memcpy(&info.vecStream[0], pStream + iStreamOffset, bSDBSize );
|
||||
iStreamOffset += bSDBSize;
|
||||
|
||||
m_mapSDBMap[dwFileNameHash] = info;
|
||||
}
|
||||
|
||||
#ifdef __THEMIDA__
|
||||
VM_END
|
||||
#endif
|
||||
|
||||
return iStreamOffset;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
#ifndef __INC_ETERPACKLIB_ETERPACKPOLICY_CSHYBRIDCRYPT_H__
|
||||
#define __INC_ETERPACKLIB_ETERPACKPOLICY_CSHYBRIDCRYPT_H__
|
||||
|
||||
#include <unordered_map>
|
||||
#include <cryptopp/cryptlib.h>
|
||||
#include <cryptopp/camellia.h>
|
||||
#include <cryptopp/twofish.h>
|
||||
#include <cryptopp/tea.h>
|
||||
|
||||
enum eHybridCipherAlgorithm
|
||||
{
|
||||
e_Cipher_Camellia,
|
||||
e_Cipher_Twofish,
|
||||
e_Cipher_XTEA,
|
||||
Num_Of_Ciphers
|
||||
};
|
||||
|
||||
|
||||
class CFileBase;
|
||||
class CLZObject;
|
||||
|
||||
//THEMIDA
|
||||
class EterPackPolicy_CSHybridCrypt
|
||||
{
|
||||
public:
|
||||
~EterPackPolicy_CSHybridCrypt();
|
||||
|
||||
bool GenerateCryptKey( std::string& rfileName );
|
||||
bool EncryptMemory( std::string& rfilename, IN const BYTE* pSrcData, IN int iSrcLen, OUT CLZObject& zObj );
|
||||
bool DecryptMemory( std::string& rfilename, IN const BYTE* pSrcData, IN int iSrcLen, OUT CLZObject& zObj );
|
||||
bool IsContainingCryptKey() const;
|
||||
|
||||
//Supplementary Data Block (SDB)
|
||||
bool GenerateSupplementaryDataBlock(std::string& rfilename, const std::string& strMapName, IN const BYTE* pSrcData, IN int iSrcLen, OUT LPBYTE& pDestData, OUT int& iDestLen );
|
||||
bool GetSupplementaryDataBlock( std::string& rfilename, OUT LPBYTE& pSDB, OUT int& iSDBSize );
|
||||
bool IsContainingSDBFile() const;
|
||||
|
||||
// Read/Write IO
|
||||
void WriteCryptKeyToFile( CFileBase& rFile );
|
||||
int ReadCryptKeyInfoFromStream( IN const BYTE* pStream );
|
||||
|
||||
void WriteSupplementaryDataBlockToFile( CFileBase& rFile );
|
||||
int ReadSupplementatyDataBlockFromStream( IN const BYTE* pStream );
|
||||
|
||||
protected:
|
||||
|
||||
typedef union UEncryptKey
|
||||
{
|
||||
BYTE key[16];
|
||||
BYTE keyCamellia[ CryptoPP::Camellia::DEFAULT_KEYLENGTH];
|
||||
BYTE keyTwofish [ CryptoPP::Twofish::DEFAULT_KEYLENGTH];
|
||||
BYTE keyXTEA [ CryptoPP::XTEA::DEFAULT_KEYLENGTH];
|
||||
|
||||
} TEncryptKey;
|
||||
|
||||
typedef union UEncryptIV
|
||||
{
|
||||
BYTE iv[16];
|
||||
BYTE ivCamellia [ CryptoPP::Camellia::BLOCKSIZE];
|
||||
BYTE ivTwofish [ CryptoPP::Twofish::BLOCKSIZE];
|
||||
BYTE ivXTEA [ CryptoPP::XTEA::BLOCKSIZE];
|
||||
|
||||
} TEncryptIV;
|
||||
|
||||
|
||||
typedef struct SCSHybridCryptKey
|
||||
{
|
||||
TEncryptKey uEncryptKey;
|
||||
TEncryptIV uEncryptIV;
|
||||
|
||||
} TCSHybridCryptKey;
|
||||
|
||||
typedef std::unordered_map<DWORD, TCSHybridCryptKey> TCSHybridCryptKeyMap;
|
||||
TCSHybridCryptKeyMap m_mapHybridCryptKey;
|
||||
|
||||
typedef struct SSupplementaryDataBlockInfo
|
||||
{
|
||||
std::string strRelatedMapName;
|
||||
std::vector<BYTE> vecStream;
|
||||
|
||||
} TSupplementaryDataBlockInfo;
|
||||
|
||||
typedef std::unordered_map<DWORD, TSupplementaryDataBlockInfo> TSupplementaryDataBlockMap; //key filename hash
|
||||
TSupplementaryDataBlockMap m_mapSDBMap;
|
||||
|
||||
private:
|
||||
bool GetPerFileCryptKey( std::string& rfileName, eHybridCipherAlgorithm& eAlgorithm, TEncryptKey& key, TEncryptIV& iv );
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __INC_ETERPACKLIB_ETERPACKPOLICY_CSHYBRIDCRYPT_H__
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef __INC_ETERPACK_INLINE_H__
|
||||
#define __INC_ETERPACK_INLINE_H__
|
||||
|
||||
inline void inlinePathCreate(const char* path)
|
||||
{
|
||||
char dir[64];
|
||||
const char* p, *k;
|
||||
|
||||
p = path + 3;
|
||||
|
||||
while (NULL != (k = strchr(p, '/')))
|
||||
{
|
||||
memset(dir, 0, sizeof(dir));
|
||||
strncpy(dir, path, k - path);
|
||||
CreateDirectory(dir, NULL);
|
||||
p = k + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void inlineConvertPackFilename(char* name)
|
||||
{
|
||||
char * p = name;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
else
|
||||
*p = (int) tolower(*p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "StdAfx.h"
|
||||
|
||||
Reference in New Issue
Block a user