|
고급 암호화 방법에 대해서 아는 바가 없고 간단한 방법을 말씀드리죠.
보통 파일을 암호화한다는 것은 같은 암호로 다시 풀 수 있음을 의미합니다.
암호를 별도로 저장하지 않는 것이 좋을 것이며 그런 경우에는 배타적 논리합 연산을 사용해야 하겠죠. Exclusive-OR 연산을 거듭해서 두 번 하면 원래 자료로 돌아오는 것은 아시죠?
char d='6' ,e ,p='7';
e = d^p; //암호화
d = e^p; //암호 풀기
(위에서 d는 원래 자료, p는 암호 ,e는 암호화된 자료.)
그리고 바이트 ,비트 바꾸기 등 다양한 방법을 사용할 수 있겠지요.
한편 주의하실 것은 될 수 있으면 암호를 그대로 사용해서는 안 됩니다.
암호를 아무런 조정 과정을 거치지 않고 그대로 사용하면 암호를 한 문자씩 입력해가며 암호를 풀 수 있는 허점이 생깁니다. 그러므로 암호의 길이와 각 자리에 있는 암호 문자가 모두 일치해야만 한 문자라도 암호가 풀릴 수 있도록 암호화 시 함호의 길이 및 각 자리의 문자를 암호화 연산에 포함시켜야 합니다.
아래 예에서는 암호를 조정하는 부분은 생략했습니다.
안전을 위해서는 암호를 조정해주어야 할 것입니다.
// 아래 함수에서 예외 처리 코드는 생략되었으므로 추가하시기 바랍니다.
// 예를 들어, stream = new TFileStream(fileName , fmOpenReadWrite);에서
// 예외가 발생할 수 있으므로 이에 대한 예외 처리 코드를 작성해주어야 합니다.
bool DoEncrypt(String fileName ,unsigned char *password)
{
if(FileExists(fileName)==false) return false;
WIN32_FILE_ATTRIBUTE_DATA fileData;
long toRead ,gotRead, fileSize ,bufferLen;
int passLen ,pn;
TFileStream *stream;
unsigned char *buffer;
GetFileAttributesEx(fileName.c_str() , GetFileExInfoStandard ,&fileData);
if(fileData. dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) return false;
if(fileData.nFileSizeHigh)
{
return false;
// TFileStream은 long 파일 포인터를 사용하므로 이를 초과하는 위치는 액세스할 수 없음.
// (따라서 최대 2GB(2의 31승) 크기의 파일만을 처리할 수 있음)
//fileSize = (MAXDWORD * fileData.nFileSizeHigh)+fileData.nFileSizeLow;
// (fileData.nFileSizeHigh에는 DWORD 단위(4, 294, 967, 295)의 크기가 기록됨)
}
// TFileStream은 long 파일 포인터를 사용하므로 이를 초과하는 위치는 액세스할 수 없음.
if(fileData.nFileSizeLow >MAXDWORD/2) return false;
//크기가 0이면 암호화가 필요 없음
if(fileData.nFileSizeLow ==0) return true;
fileSize =fileData.nFileSizeLow;
//쓰기 작업이 가능하도록 파일 속성을 해제
SetFileAttributes(fileName.c_str(), 0);
passLen = strlen(password);
//메모리 확보(될 수 있으면 커야 처리 속도가 빠름)
if(fileSize<1024l*120l) bufferLen=fileSize;
else bufferLen = 1024l*120l;
while(1)
{
buffer = new unsigned char[bufferLen];
if(buffer) break;
bufferLen -= 1024l;
if(bufferLen<1024) return false;
};
toRead = bufferLen;
//파일을 읽기 및 쓰기 모드로 열기
stream = new TFileStream(fileName , fmOpenReadWrite)
stream->Seek(0,soFromBeginning);
gotRead=0;
//pn은 여기에서만 초기화하고 아래 do루프 내의 for 루프 시작시에는 초기화하면 안 됨.
pn=0;
do
{
stream->Read((void*)buffer ,toRead);
//암호화(이 부분을 변경할 때에는 세심한 주의가 필요합니다.)
for(register long n=0; n<toRead ;n++)
{
buffer[n] = buffer[n]^password[pn]^(unsigned char)pn;
if(++pn>=passLen) pn=0;
}
stream->Seek(gotRead,soFromBeginning);
stream->Write((void*)buffer ,toRead);
gotRead += toRead;
toRead=(toRead+gotRead<=fileSize)?toRead:fileSize-gotRead;
}while(gotRead<fileSize);
// 파일 닫기 및 메모리 반납
delete stream;
delete buffer;
//파일 속성 복원
SetFileAttributes(fileName.c_str() ,fileData.dwFileAttributes);
return true;
} //end of function
끝.
|