BSOne.SFC/eCrmHE/Utils/EXE_Bs1Drm4c/Bs1Drm4c.cpp

220 lines
5.6 KiB
C++

// Bs1Drm4c.cpp : 이 파일에는 'main' 함수가 포함됩니다. 거기서 프로그램 실행이 시작되고 종료됩니다.
//
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include "aes.hpp"
#define DRM_VER 2
#define MAX_HEAD_STR 260
#define PASS_DRM_HEAD "#df12mf8(zfq@"
#define PASS_DRM_DATA "M}[8k(Ga1/<;LE1j&q"
#define SIG_DRM "ToCSG"
#define UNIX_EPOCH 25569.0 // Unix Epoch (1970년 1월 1일)을 Julian Date 기준으로 계산한 값
#define SECONDS_IN_A_DAY 86400.0 // 하루에 포함된 초의 수
#pragma pack(push, 1)
typedef struct {
uint16_t wVer;
uint32_t dwCustomerCode;
char sEmpNo[MAX_HEAD_STR];
char sHostName[MAX_HEAD_STR];
char sPartName[MAX_HEAD_STR];
char sPgName[MAX_HEAD_STR];
char sReserve1[MAX_HEAD_STR];
char sReserve2[MAX_HEAD_STR];
double dtEnc;
//uint64_t dtEnc;
} TTgDrmHead; // size = 1574
#pragma pack(pop)
int StrKeyToBitPadding(const char* sKey, uint8_t** aBuf)
{
int nResult = 0;
int nBit = 256;
char cFillChar = '*';
*aBuf = (uint8_t*)malloc(nBit);
if (*aBuf == NULL)
return nResult;
memset(*aBuf, cFillChar, nBit);
int nKeyLen = strlen(sKey);
if (nKeyLen > nBit) {
memcpy(*aBuf, sKey, nBit);
}
else {
memcpy(*aBuf, sKey, nKeyLen);
}
nResult = nBit * 8;
return nResult;
}
bool CheckSig(FILE* fs)
{
int nLen = strlen(SIG_DRM);
char* pBuf = (char*)malloc(nLen);
if (pBuf == NULL)
return false;
fseek(fs, 0, SEEK_SET);
if (nLen != fread(pBuf, 1, nLen, fs))
{
free(pBuf);
return false;
}
bool bResult = memcmp(pBuf, SIG_DRM, nLen) == 0;
free(pBuf);
return bResult;
}
void CutTail(char* src)
{
char* pos = strstr(src, "§+");
if (pos == NULL)
{
pos = strstr(src, "짠+");
if (pos == NULL)
return;
}
int nPos = pos - src;
src[nPos] = '\0';
}
time_t DelphiDateTimeToUnixTimestamp(double dt)
{
return (time_t)((dt - UNIX_EPOCH) * SECONDS_IN_A_DAY);
}
bool ExtrHead(FILE* fs, TTgDrmHead* aHead)
{
int nLen = sizeof(TTgDrmHead); // 1574
//int nEncLen = nLen - (nLen % 16) - 16;
//int nDum = nLen - nEncLen;
/*if (nLen % 16)
nLen += 16 - (nLen % 16);*/
uint8_t* pBuf = (uint8_t*)malloc(nLen);
if (pBuf == NULL)
return false;
memset(pBuf, 0, sizeof(nLen));
if (nLen != fread(pBuf, 1, nLen, fs))
{
free(pBuf);
return false;
}
uint8_t* pKey = NULL;
if (0 == StrKeyToBitPadding(PASS_DRM_HEAD, &pKey))
{
free(pBuf);
return false;
}
uint8_t IV[AES_BLOCKLEN];
memcpy(IV, pKey, AES_BLOCKLEN);
AES_ctx ctx;
memset(&ctx, 0, sizeof(ctx));
AES_init_ctx_iv(&ctx, pKey, IV);
//AES_init_ctx(&ctx, pKey);
AES_CBC_decrypt_buffer(&ctx, pBuf, nLen);
//if (nDum > 0)
//{
// if (nDum != fread(&pBuf[nEncLen], 1, nDum, fs))
// {
// free(pBuf);
// return false;
// }
//}
memcpy(aHead, pBuf, nLen);
CutTail(aHead->sEmpNo);
CutTail(aHead->sHostName);
CutTail(aHead->sPartName);
CutTail(aHead->sPgName);
FILE* ff = NULL;
fopen_s(&ff, "C:\\taskToCSG\\eCrmHE\\Utils\\EXE_Bs1Drm4c\\x64\\Debug\\test.dat", "wb");
fwrite(pBuf, 1, nLen, ff);
fclose(ff);
free(pBuf);
return true;
}
int main(int argc, char* argv[])
{
//printf("msg - %s, size - %d", argv[0], sizeof(uint16_t));
FILE* fs = NULL;
//char* path = argv[1];
char sPath[] = "C:\\taskToCSG\\eCrmHE\\Utils\\EXE_Bs1Drm4c\\x64\\Debug\\워터마크 샘플_enc.pdf"; // argv[1];
try
{
if (0 != fopen_s(&fs, sPath, "rb"))
{
printf("Fail .. FileOpen(), Path = %s\n", sPath);
return 1;
}
if (false == CheckSig(fs))
{
fclose(fs);
printf("Fail .. CheckSig(), Path = %s\n", sPath);
return 1;
}
TTgDrmHead head;
memset(&head, 0, sizeof(head));
if (false == ExtrHead(fs, &head))
{
fclose(fs);
printf("Fail .. ExtrHead(), Path = %s\n", sPath);
return 1;
}
printf("Ver = %d, HostName = %s\n", head.wVer, head.sHostName);
//time_t unixTimestamp = DelphiDateTimeToUnixTimestamp(head.dtEnc);
//struct tm ts;
//gmtime_s(&ts, &unixTimestamp);
////if (0 == gmtime_s(&ts, &unixTimestamp))
////{
// char buffer[80];
// strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &ts);
// printf("Date and Time: %s\n", buffer);
////}
fclose(fs);
}
catch (const char* e) {
printf("Exception: %s\n", e);
}
}
// 프로그램 실행: <Ctrl+F5> 또는 [디버그] > [디버깅하지 않고 시작] 메뉴
// 프로그램 디버그: <F5> 키 또는 [디버그] > [디버깅 시작] 메뉴
// 시작을 위한 팁:
// 1. [솔루션 탐색기] 창을 사용하여 파일을 추가/관리합니다.
// 2. [팀 탐색기] 창을 사용하여 소스 제어에 연결합니다.
// 3. [출력] 창을 사용하여 빌드 출력 및 기타 메시지를 확인합니다.
// 4. [오류 목록] 창을 사용하여 오류를 봅니다.
// 5. [프로젝트] > [새 항목 추가]로 이동하여 새 코드 파일을 만들거나, [프로젝트] > [기존 항목 추가]로 이동하여 기존 코드 파일을 프로젝트에 추가합니다.
// 6. 나중에 이 프로젝트를 다시 열려면 [파일] > [열기] > [프로젝트]로 이동하고 .sln 파일을 선택합니다.