보안인증확인서 사용자 인증 및 암복호화
1. 사용자 인증 : Tocsg.Module\UserAuthentification 2. 암복호화 클래스 - Tocsg.Lib\VCL\Tocsg.COLib.Encrypt.pas - Tocsg.Lib\VCL\Tocsg.COLib.pas 3. 캠페인 및 암호화 - Tocsg.Module\ContentSearch\EXE_KvCttSch\ThdCttSch.pas
This commit is contained in:
parent
c2ba523c24
commit
a2da00c688
|
|
@ -0,0 +1,664 @@
|
|||
unit Tocsg.COLib.Encrypt;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Winapi.Windows, System.SysUtils, System.Classes, Vcl.Dialogs, System.Math, System.IOUtils,
|
||||
Tocsg.COLib, Tocsg.Safe;
|
||||
|
||||
const
|
||||
SIG_CO_DRM = 'ToCSG_CO';
|
||||
DRM_CO_VER = 1;
|
||||
MAX_HEAD_STR = 260;
|
||||
|
||||
type
|
||||
// 헤더 구조체 (Packed로 선언하여 메모리 정렬 고정)
|
||||
TTgDrmHead = packed record
|
||||
wVer: WORD;
|
||||
dwCustomerCode: DWORD;
|
||||
sEmpNo,
|
||||
sHostName,
|
||||
sPartName,
|
||||
sPgName: array [0..MAX_HEAD_STR - 1] of UTF8Char;
|
||||
dtEnc: TDateTime;
|
||||
end;
|
||||
|
||||
TTgColibDrm = class
|
||||
private
|
||||
class function EncryptKEK(const pKek: TBytes; const sFilePath: string): Boolean;
|
||||
class function DecryptKEK(const sPath: string): TBytes;
|
||||
class procedure EncryptDEKtoKEK(const pDek, pKek: TBytes);
|
||||
class function DecryptDEKtoKEK(sPath:string; pKek:TBytes): TBytes;
|
||||
class function CheckSig(aStream: TStream): Boolean;
|
||||
// 헤더 정보를 읽고 복호화하여 스트림 위치를 데이터 시작점으로 이동
|
||||
class function ExtractHead(aSrcStream: TStream; pDek: TBytes; var aHead: TTgDrmHead): Boolean;
|
||||
public
|
||||
class function CreateSalt(const iKeylen: Integer): TBytes;
|
||||
class function CreateKEK(const sPass, sSalt: AnsiString; Iterations, iKeyLen: Integer): TBytes;
|
||||
class procedure CreateDEK(const iKeylen: Integer; pKek: TBytes);
|
||||
class function GetKEK(sPath:string ): TBytes;
|
||||
class function GetDEK(sPath:string; pKek:TBytes): TBytes;
|
||||
// 헤더 정보를 생성하고 파일 스트림에 기록
|
||||
//class function SetHead(aDstStream: TStream; pDek: TBytes; sEmpNo, sHostName, sPartName, sPgName: UTF8String): Boolean;
|
||||
//class procedure DoEncrypt(sPath: string; pDek: TBytes; sEmpNo, sHostName, sPartName, sPgName: UTF8String);
|
||||
class function SetHead(aDstStream: TStream; pDek: TBytes): Boolean;
|
||||
class function DoEncrypt(sPath: string; pDek: TBytes): Boolean;
|
||||
class procedure DoDecrypt(sPath: string; pDek: TBytes);
|
||||
class function IsEncrypt(sPath: string): Boolean;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{ TTgColibDrm }
|
||||
|
||||
type
|
||||
TDataBlob = record
|
||||
cbData: DWORD;
|
||||
pbData: PByte;
|
||||
end;
|
||||
PDataBlob = ^TDataBlob;
|
||||
|
||||
function CryptProtectData(pDataIn: PDataBlob; szDataDescr: PWideChar;
|
||||
pOptionalEntropy: PDataBlob; pvReserved: Pointer; pPromptStruct: Pointer;
|
||||
dwFlags: DWORD; pDataOut: PDataBlob): BOOL; stdcall;
|
||||
external 'crypt32.dll' name 'CryptProtectData';
|
||||
|
||||
function CryptUnprotectData(pDataIn: PDataBlob; ppszDataDescr: PPWideChar;
|
||||
pOptionalEntropy: PDataBlob; pvReserved: Pointer; pPromptStruct: Pointer;
|
||||
dwFlags: DWORD; pDataOut: PDataBlob): BOOL; stdcall;
|
||||
external 'crypt32.dll' name 'CryptUnprotectData';
|
||||
|
||||
function ConcatBytes(const pBuf1, pBuf2: TBytes): TBytes;
|
||||
begin
|
||||
SetLength(Result, Length(pBuf1) + Length(pBuf2));
|
||||
Move(pBuf1[0], Result[0], Length(pBuf1));
|
||||
Move(pBuf2[0], Result[Length(pBuf1)], Length(pBuf2));
|
||||
end;
|
||||
|
||||
procedure XORBytes(var pBuf1: TBytes; const pBuf2: TBytes);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
for i := 0 to Min(Length(pBuf1), Length(pBuf2)) - 1 do
|
||||
pBuf1[i] := pBuf1[i] xor pBuf2[i];
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.CreateSalt(const iKeylen: Integer): TBytes;
|
||||
var
|
||||
nResult: Integer;
|
||||
pSalt: TBytes;
|
||||
sPath: string;
|
||||
begin
|
||||
sPath := 'salt.bin';
|
||||
|
||||
if TFile.Exists(sPath) then
|
||||
begin
|
||||
Result := TFile.ReadAllBytes(sPath);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// 파일이 없는 경우: 새로운 Salt 생성
|
||||
SetLength(pSalt, iKeylen);
|
||||
|
||||
// SHA-256 난수
|
||||
nResult := COLibDrbg(@pSalt[0], Length(pSalt), nil, 0, nil, 0, 0);
|
||||
if nResult = COLIB_SUCCESS then
|
||||
begin
|
||||
// 생성 성공 시 파일로 기록
|
||||
try
|
||||
TFile.WriteAllBytes(sPath, pSalt);
|
||||
Result := pSalt;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
ShowMessage('Salt 파일 저장 중 오류: ' + E.Message);
|
||||
Result := nil;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// 생성 실패 시 처리
|
||||
ShowMessage('Salt 생성 실패: ' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult));
|
||||
Result := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.EncryptKEK(const pKek: TBytes; const sFilePath: string): Boolean;
|
||||
var
|
||||
DataIn, DataOut: TDataBlob;
|
||||
FileStream: TFileStream;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
if Length(pKek) = 0 then
|
||||
begin
|
||||
ShowMessage('KEK가 비어있습니다.');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// TBytes 데이터를 DataIn 구조체에 연결
|
||||
DataIn.pbData := @pKek[0];
|
||||
DataIn.cbData := Length(pKek);
|
||||
|
||||
// DPAPI 암호화 호출 (현재 사용자 계정으로만 복호화 가능하도록 설정)
|
||||
// 세 번째 인자는 엔트로피(추가 암호)
|
||||
if CryptProtectData(@DataIn, nil, nil, nil, nil, 0, @DataOut) then
|
||||
begin
|
||||
try
|
||||
FileStream := TFileStream.Create(sFilePath, fmCreate);
|
||||
try
|
||||
FileStream.WriteBuffer(DataOut.pbData^, DataOut.cbData);
|
||||
Result := True;
|
||||
finally
|
||||
FileStream.Free;
|
||||
end;
|
||||
finally
|
||||
// DPAPI에서 할당한 메모리 해제
|
||||
LocalFree(HLOCAL(DataOut.pbData));
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ShowMessage('CryptProtectData is failed: ' + IntToStr(GetLastError));
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.DecryptKEK(const sPath: string): TBytes;
|
||||
var
|
||||
DataIn, DataOut: TDataBlob;
|
||||
ms: TMemoryStream;
|
||||
begin
|
||||
SetLength(Result, 0);
|
||||
|
||||
if not FileExists(sPath) then
|
||||
begin
|
||||
ShowMessage('KEK가 존재하지 않습니다');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
ms := TMemoryStream.Create;
|
||||
try
|
||||
ms.LoadFromFile(sPath);
|
||||
DataIn.pbData := ms.Memory;
|
||||
DataIn.cbData := ms.Size;
|
||||
|
||||
// DPAPI 복호화 호출
|
||||
if CryptUnprotectData(@DataIn, nil, nil, nil, nil, 0, @DataOut) then
|
||||
begin
|
||||
try
|
||||
// 복호화된 바이너리 데이터를 TBytes로 복사
|
||||
SetLength(Result, DataOut.cbData);
|
||||
if DataOut.cbData > 0 then
|
||||
Move(DataOut.pbData^, Result[0], DataOut.cbData);
|
||||
finally
|
||||
LocalFree(HLOCAL(DataOut.pbData));
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ShowMessage('CryptUnprotectData is failed: ' + IntToStr(GetLastError));
|
||||
end;
|
||||
finally
|
||||
ms.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.CreateKEK(const sPass, sSalt: AnsiString; Iterations, iKeyLen: Integer): TBytes;
|
||||
var
|
||||
i, n, nBlockCnt: Integer;
|
||||
pSaltAndBlkIdx, pBlockIdx, pTemp, U_prev, U_current, pPass, pSalt: TBytes;
|
||||
ci: TCIPHER_INFO;
|
||||
nOut, nResult: Integer;
|
||||
path: string;
|
||||
begin
|
||||
path := 'kek.bin';
|
||||
|
||||
if TFile.Exists(path) then
|
||||
begin
|
||||
// 파일이 존재하면 복호화후 리턴
|
||||
//ShowMessage('실제 감지된 경로: ' + TPath.GetFullPath(path));
|
||||
Result := DecryptKEK(path);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SetLength(Result, iKeyLen);
|
||||
ZeroMemory(Result, iKeyLen);
|
||||
|
||||
if (sPass = '') or (sSalt = '') then
|
||||
exit;
|
||||
|
||||
n := Length(sPass);
|
||||
if n < 16 then
|
||||
begin
|
||||
SetLength(pPass, 16);
|
||||
ZeroMemory(pPass, 16);
|
||||
end else
|
||||
SetLength(pPass, n);
|
||||
CopyMemory(pPass, @sPass[1], n);
|
||||
|
||||
n := Length(sSalt);
|
||||
SetLength(pSalt, n);
|
||||
CopyMemory(pSalt, @sSalt[1], n);
|
||||
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
|
||||
SetLength(pBlockIdx, 4);
|
||||
SetLength(pTemp, iKeyLen);
|
||||
SetLength(U_prev, iKeyLen);
|
||||
SetLength(U_current, iKeyLen);
|
||||
|
||||
// PBKDF
|
||||
// 32바이트 단위(SHA256)의 각 블록마다 다음을 수행
|
||||
// 1) U₁ = HMAC(Pass, Salt || BlockIndex)
|
||||
// 2) U_n = HMAC(Pass, U_{n-1})
|
||||
// 3) U_{n-1} XOR U_n
|
||||
|
||||
// 32 바이트씩 나눠서 블록개수 계산
|
||||
nBlockCnt := (iKeyLen + 31) div iKeyLen; // SHA256 = 32 bytes
|
||||
for i := 1 to nBlockCnt do
|
||||
begin
|
||||
// BlockIndex = i (Big Endian)
|
||||
// 블록 번호를 Big Endian으로 표현한 4바이트 ex) i=[0,0,0,1]
|
||||
// int(i)로 표현
|
||||
pBlockIdx[0] := Byte((i shr 24) and $FF);
|
||||
pBlockIdx[1] := Byte((i shr 16) and $FF);
|
||||
pBlockIdx[2] := Byte((i shr 8) and $FF);
|
||||
pBlockIdx[3] := Byte(i and $FF);
|
||||
|
||||
// Salt || int(i)
|
||||
pSaltAndBlkIdx := ConcatBytes(pSalt, pBlockIdx);
|
||||
|
||||
nOut := 0;
|
||||
// 1) U₁ = HMAC(Pass, Salt || BlockIndex)
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_HMAC, BLOCK_CRYPTO_MODE_UNUSED, COLIB_PAD_TYPE_UNUSED,
|
||||
@pPass[0], Length(pPass), nil, 0, @pSaltAndBlkIdx[0], Length(pSaltAndBlkIdx), @U_prev[0], @nOut);
|
||||
nResult := COLibEncrypt(@ci);
|
||||
if nResult <> COLIB_SUCCESS then
|
||||
exit;
|
||||
|
||||
CopyMemory(pTemp, U_prev, Length(U_prev));
|
||||
|
||||
for n := 2 to Iterations do
|
||||
begin
|
||||
nOut := 0;
|
||||
// 2) U_n = HMAC(Pass, U_{n-1})
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_HMAC, BLOCK_CRYPTO_MODE_UNUSED, COLIB_PAD_TYPE_UNUSED,
|
||||
@pPass[0], Length(pPass), nil, 0, @U_prev[0], Length(U_prev), @U_current[0], @nOut);
|
||||
nResult := COLibEncrypt(@ci);
|
||||
if nResult <> COLIB_SUCCESS then
|
||||
exit;
|
||||
|
||||
// 3) U_{n-1} XOR U_n
|
||||
XORBytes(pTemp, U_current);
|
||||
CopyMemory(U_prev, U_current, Length(U_current));
|
||||
end;
|
||||
|
||||
Move(pTemp[0], Result[(i - 1) * iKeyLen], Min(iKeyLen, iKeyLen - (i - 1) * iKeyLen));
|
||||
end;
|
||||
|
||||
if not (EncryptKEK(Result, path)) then
|
||||
begin
|
||||
ZeroMemory(Result, iKeyLen);
|
||||
ShowMessage('EncryptKEK is failed');
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.GetKEK(sPath:string): TBytes;
|
||||
begin
|
||||
if TFile.Exists(sPath) then
|
||||
begin
|
||||
Result := DecryptKEK(sPath);
|
||||
end
|
||||
else
|
||||
begin
|
||||
//ShowMessage('KEK가 존재하지 않습니다');
|
||||
Result := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.GetDEK(sPath:string; pKek:TBytes): TBytes;
|
||||
begin
|
||||
if TFile.Exists(sPath) then
|
||||
begin
|
||||
Result := DecryptDEKtoKEK(sPath, pKek);
|
||||
end
|
||||
else
|
||||
begin
|
||||
//ShowMessage('DEK가 존재하지 않습니다.');
|
||||
Result := nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TTgColibDrm.EncryptDEKtoKEK(const pDek, pKek: TBytes);
|
||||
var
|
||||
nResult, nOut: Integer;
|
||||
ci: TCIPHER_INFO;
|
||||
arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte;
|
||||
arrEnc: TBytes;
|
||||
sOut, sIn: string;
|
||||
begin
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
ZeroMemory(@arrIV, SizeOf(arrIV));
|
||||
|
||||
SetLength(arrEnc, Length(pDek)*2);
|
||||
|
||||
// for var i := 0 to Length(pDek) - 1 do
|
||||
// sIn := sIn + Format('%.2x', [pDek[i]]);
|
||||
// ShowMessage('평문 DEK (Hex) : ' + Inttostr(Length(pDek))+', '+sIn);
|
||||
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_NO,
|
||||
@pKek[0], Length(pKek), @arrIV, SizeOf(arrIV),
|
||||
@pDek[0], Length(pDek), @arrEnc[0], @nOut);
|
||||
|
||||
nResult := COLibEncrypt(@ci);
|
||||
if nResult <> COLIB_SUCCESS then
|
||||
begin
|
||||
ShowMessage('COLibEncrypt is failed: ' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// for var i := 0 to nOut - 1 do
|
||||
// sOut := sOut + Format('%.2x', [arrEnc[i]]);
|
||||
// ShowMessage('암호화 DEK (Hex) : ' + Inttostr(nOut)+', '+sOut);
|
||||
|
||||
// 암호화된 DEK를 바이너리 그대로 파일에 저장
|
||||
TFile.WriteAllBytes('dek.bin', Copy(arrEnc, 0, nOut));
|
||||
end;
|
||||
|
||||
class procedure TTgColibDrm.CreateDEK(const iKeylen: Integer; pKek: TBytes);
|
||||
var
|
||||
pDek: TBytes;
|
||||
sPath: string;
|
||||
begin
|
||||
sPath := 'dek.bin';
|
||||
|
||||
if TFile.Exists(sPath) then
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
|
||||
SetLength(pDek, iKeylen);
|
||||
COLibGetKey(@pDek[0], iKeylen);
|
||||
|
||||
EncryptDEKtoKEK(pDek, pKek);
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.DecryptDEKtoKEK(sPath:string; pKek:TBytes): TBytes;
|
||||
var
|
||||
nResult, nOut: Integer;
|
||||
ci: TCIPHER_INFO;
|
||||
arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte;
|
||||
arrDec, encDek: TBytes;
|
||||
sOut, sIn: string;
|
||||
begin
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
ZeroMemory(@arrIV, SizeOf(arrIV));
|
||||
|
||||
// if not TFile.Exists(sPath) then
|
||||
// begin
|
||||
// ShowMessage('DEK 존재하지 않음');
|
||||
// Result := nil;
|
||||
// Exit;
|
||||
// end;
|
||||
|
||||
encDek := TFile.ReadAllBytes(sPath);
|
||||
|
||||
SetLength(arrDec, Length(encDek)); // 암호문 길이만큼 버퍼 확보
|
||||
|
||||
// for var i := 0 to Length(encDek) - 1 do
|
||||
// sIn := sIn + Format('%.2x', [encDek[i]]);
|
||||
// ShowMessage('암호화된 DEK (Hex) : ' + Inttostr(Length(encDek))+', '+sIn);
|
||||
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_NO,
|
||||
@pKek[0], Length(pKek), @arrIV, SizeOf(arrIV),
|
||||
@encDek[0], Length(encDek), @arrDec[0], @nOut);
|
||||
|
||||
nResult := COLibDecrypt(@ci);
|
||||
if nResult <> COLIB_SUCCESS then
|
||||
begin
|
||||
ShowMessage('COLibDecrypt is failed: ' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult));
|
||||
Result := nil;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// 실제 복호화된 길이만큼 잘라내기
|
||||
//SetLength(arrDec, nOut);
|
||||
|
||||
// for var i := 0 to nOut - 1 do
|
||||
// sOut := sOut + Format('%.2x', [arrDec[i]]);
|
||||
// ShowMessage('복호화 DEK (Hex) : ' + Inttostr(Length(arrDec))+', '+sOut);
|
||||
|
||||
Result := arrDec;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.CheckSig(aStream: TStream): Boolean;
|
||||
var
|
||||
sSig: AnsiString;
|
||||
pBuf: array[0..7] of AnsiChar; // SIG_CO_DRM 길이만큼
|
||||
begin
|
||||
Result := False;
|
||||
if aStream.Size < Length(SIG_CO_DRM) then Exit;
|
||||
|
||||
aStream.Position := 0;
|
||||
aStream.Read(pBuf, Length(SIG_CO_DRM));
|
||||
sSig := Copy(pBuf, 0, Length(SIG_CO_DRM));
|
||||
|
||||
Result := (sSig = SIG_CO_DRM);
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.IsEncrypt(sPath: string): Boolean;
|
||||
var
|
||||
fs: TFileStream;
|
||||
begin
|
||||
Result := False;
|
||||
if not FileExists(sPath) then Exit;
|
||||
|
||||
try
|
||||
Guard(fs, TFileStream.Create(sPath, fmOpenRead or fmShareDenyNone));
|
||||
Result := CheckSig(fs);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.SetHead(aDstStream: TStream; pDek: TBytes): Boolean;
|
||||
var
|
||||
Head: TTgDrmHead;
|
||||
ci: TCIPHER_INFO;
|
||||
arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte;
|
||||
pEncHead: TBytes;
|
||||
nOut, nResult: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
ZeroMemory(@Head, SizeOf(Head));
|
||||
Head.wVer := DRM_CO_VER;
|
||||
Head.dwCustomerCode := 13001;
|
||||
Head.dtEnc := Now;
|
||||
//Head.llEncDT := DelphiDtToJavaDt(Now);
|
||||
StrCopy(Head.sPgName, PUTF8Char(SIG_CO_DRM));
|
||||
StrCopy(Head.sEmpNo, PUTF8Char(SIG_CO_DRM));
|
||||
StrCopy(Head.sPartName, PUTF8Char(SIG_CO_DRM));
|
||||
StrCopy(Head.sHostName, PUTF8Char(SIG_CO_DRM));
|
||||
// Move(PAnsiChar(sEmpNo)^, Head.sEmpNo[0], Min(Length(sEmpNo), MAX_HEAD_STR));
|
||||
// Move(PAnsiChar(sHostName)^, Head.sHostName[0], Min(Length(sHostName), MAX_HEAD_STR));
|
||||
// Move(PAnsiChar(sPartName)^, Head.sPartName[0], Min(Length(sPartName), MAX_HEAD_STR));
|
||||
// Move(PAnsiChar(sPgName)^, Head.sPgName[0], Min(Length(sPgName), MAX_HEAD_STR));
|
||||
|
||||
// 헤더 암호화
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
ZeroMemory(@arrIV, SizeOf(arrIV));
|
||||
SetLength(pEncHead, SizeOf(Head) + 16); // 패딩 고려
|
||||
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_PKCS,
|
||||
@pDek[0], Length(pDek), @arrIV, SizeOf(arrIV),
|
||||
@Head, SizeOf(Head), @pEncHead[0], @nOut);
|
||||
|
||||
nResult := COLibEncrypt(@ci);
|
||||
if nResult = COLIB_SUCCESS then
|
||||
begin
|
||||
// 암호화된 헤더 길이(Integer, 4byte)를 먼저 쓰고 데이터를 씀 (복호화 시 필요)
|
||||
aDstStream.Write(nOut, SizeOf(Integer));
|
||||
aDstStream.Write(pEncHead[0], nOut);
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.DoEncrypt(sPath: string; pDek: TBytes): Boolean;
|
||||
const
|
||||
BUF_LEN_64K = 1024 * 64;
|
||||
var
|
||||
fsSrc, fsDst: TFileStream;
|
||||
arrBuf: array [0..BUF_LEN_64K-1] of Byte;
|
||||
arrEnc: array [0..BUF_LEN_64K + 31] of Byte; // 패딩 대비 여유 공간
|
||||
dwRead: DWORD;
|
||||
nOut, nResult: Integer;
|
||||
pt: TCOLIB_PAD_TYPE;
|
||||
ci: TCIPHER_INFO;
|
||||
arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte;
|
||||
sSig: AnsiString;
|
||||
begin
|
||||
sSig := SIG_CO_DRM;
|
||||
ZeroMemory(@arrIV, SizeOf(arrIV));
|
||||
|
||||
Guard(fsSrc, TFileStream.Create(sPath, fmOpenRead));
|
||||
Guard(fsDst, TFileStream.Create(sPath + '.enc', fmCreate));
|
||||
|
||||
// 시그니처 (평문)
|
||||
fsDst.Write(sSig[1], Length(sSig));
|
||||
|
||||
if not SetHead(fsDst, pDek) then Exit;
|
||||
|
||||
while fsSrc.Position < fsSrc.Size do
|
||||
begin
|
||||
dwRead := fsSrc.Read(arrBuf, BUF_LEN_64K);
|
||||
|
||||
// 마지막 블록인 경우 패딩 처리
|
||||
if fsSrc.Position >= fsSrc.Size then
|
||||
pt := COLIB_PAD_TYPE_PKCS
|
||||
else
|
||||
pt := COLIB_PAD_TYPE_NO;
|
||||
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, pt,
|
||||
@pDek[0], Length(pDek), @arrIV, SizeOf(arrIV),
|
||||
@arrBuf, dwRead, @arrEnc, @nOut);
|
||||
|
||||
nResult := COLibEncrypt(@ci);
|
||||
if nResult <> COLIB_SUCCESS then
|
||||
begin
|
||||
ShowMessage('파일 암호화 실패: ' + IntToStr(nResult));
|
||||
Result := False;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
fsDst.Write(arrEnc, nOut);
|
||||
Result := True;
|
||||
|
||||
// CBC 모드이므로 다음 블록의 IV는 현재 암호문의 마지막 블록이어야 함 (라이브러리 내부 처리 확인 필요)
|
||||
// 만약 라이브러리가 IV를 자동 갱신하지 않는다면 여기서 마지막 암호문 블록을 arrIV에 복사해야 한다.
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TTgColibDrm.ExtractHead(aSrcStream: TStream; pDek: TBytes; var aHead: TTgDrmHead): Boolean;
|
||||
var
|
||||
nEncHeadLen, nOut, nResult: Integer;
|
||||
pEncBuf, pDecBuf: TBytes;
|
||||
ci: TCIPHER_INFO;
|
||||
arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte;
|
||||
begin
|
||||
Result := False;
|
||||
|
||||
// 암호화된 헤더 길이 (4바이트)
|
||||
if aSrcStream.Read(nEncHeadLen, SizeOf(Integer)) <> SizeOf(Integer) then Exit;
|
||||
|
||||
// 암호화된 헤더 본문
|
||||
SetLength(pEncBuf, nEncHeadLen);
|
||||
if aSrcStream.Read(pEncBuf[0], nEncHeadLen) <> nEncHeadLen then Exit;
|
||||
|
||||
// 헤더 복호화
|
||||
SetLength(pDecBuf, nEncHeadLen);
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
ZeroMemory(@arrIV, SizeOf(arrIV));
|
||||
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_PKCS,
|
||||
@pDek[0], Length(pDek), @arrIV, SizeOf(arrIV),
|
||||
@pEncBuf[0], nEncHeadLen, @pDecBuf[0], @nOut);
|
||||
|
||||
nResult := COLibDecrypt(@ci);
|
||||
if nResult = COLIB_SUCCESS then
|
||||
begin
|
||||
Move(pDecBuf[0], aHead, SizeOf(TTgDrmHead));
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TTgColibDrm.DoDecrypt(sPath: string; pDek:TBytes);
|
||||
const
|
||||
BUF_LEN_64K = 1024 * 64;
|
||||
var
|
||||
fsSrc, fsDst: TFileStream;
|
||||
arrBuf: array [0..BUF_LEN_64K - 1] of Byte;
|
||||
arrDec: array [0..BUF_LEN_64K + 31] of Byte; // 패딩 대비 여유 공간
|
||||
dwRead: DWORD;
|
||||
nOut, nResult: Integer;
|
||||
pt: TCOLIB_PAD_TYPE;
|
||||
ci: TCIPHER_INFO;
|
||||
arrIV: array [0..COLIB_BLOCK_LEN - 1] of Byte;
|
||||
HeaderInfo: TTgDrmHead; // 복호화된 헤더 정보를 담을 변수
|
||||
begin
|
||||
Guard(fsSrc, TFileStream.Create(sPath, fmOpenRead or fmShareDenyNone));
|
||||
// 기존 파일명에서 .enc가 있다면 제거하고 .dec를 붙임
|
||||
Guard(fsDst, TFileStream.Create(ChangeFileExt(sPath, '') + '.dec', fmCreate));
|
||||
|
||||
try
|
||||
// 시그니처 위치(8바이트) 건너뛰기
|
||||
fsSrc.Position := Length(SIG_CO_DRM);
|
||||
|
||||
// 헤더 추출 및 복호화 (데이터 시작 지점으로 스트림 포인터 이동)
|
||||
if not ExtractHead(fsSrc, pDek, HeaderInfo) then
|
||||
begin
|
||||
ShowMessage('헤더 복호화에 실패했습니다. 키 값이 올바르지 않을 수 있습니다.');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
// 복호화된 헤더 정보 활용
|
||||
// ShowMessage('복호화 대상 사번: ' + string(UTF8String(HeaderInfo.sEmpNo)));
|
||||
|
||||
ZeroMemory(@arrIV, SizeOf(arrIV));
|
||||
|
||||
while fsSrc.Position < fsSrc.Size do
|
||||
begin
|
||||
dwRead := fsSrc.Read(arrBuf, BUF_LEN_64K);
|
||||
|
||||
// 스트림의 마지막 블록인 경우에만 PKCS 패딩 적용
|
||||
if fsSrc.Position >= fsSrc.Size then
|
||||
pt := COLIB_PAD_TYPE_PKCS
|
||||
else
|
||||
pt := COLIB_PAD_TYPE_NO;
|
||||
|
||||
ZeroMemory(@ci, SizeOf(ci));
|
||||
COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, pt,
|
||||
@pDek[0], Length(pDek), @arrIV, SizeOf(arrIV),
|
||||
@arrBuf, dwRead, @arrDec, @nOut);
|
||||
|
||||
nResult := COLibDecrypt(@ci);
|
||||
if nResult <> COLIB_SUCCESS then
|
||||
begin
|
||||
ShowMessage('데이터 복호화 중 오류 발생: ' + IntToStr(nResult));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
fsDst.Write(arrDec, nOut);
|
||||
end;
|
||||
|
||||
//ShowMessage('복호화가 완료되었습니다.');
|
||||
|
||||
except
|
||||
on E: Exception do
|
||||
ShowMessage('복호화 중 예외 발생: ' + E.Message);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,533 @@
|
|||
{*******************************************************}
|
||||
{ }
|
||||
{ Tocsg.COLib }
|
||||
{ }
|
||||
{ Copyright (C) 2025 kku }
|
||||
{ }
|
||||
{*******************************************************}
|
||||
|
||||
unit Tocsg.COLib;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
System.SysUtils, Winapi.Windows;
|
||||
|
||||
const
|
||||
{$IFDEF WIN64}
|
||||
DLL_COLIB = 'colib64.dll';
|
||||
{$ELSE}
|
||||
DLL_COLIB = 'colib.dll';
|
||||
{$ENDIF}
|
||||
|
||||
(*************** Definitions / Macros *************************************)
|
||||
MEM_MARGIN_1 = 1;
|
||||
MPZ_WORD_LEN = 500 + MEM_MARGIN_1;
|
||||
|
||||
COLIB_BLOCK_LEN = 16;
|
||||
SHA512_DIGEST_SIZE = 64;
|
||||
SHA256_DIGEST_SIZE = 32;
|
||||
|
||||
COLIB_128BIT_KEY_LEN = 16;
|
||||
COLIB_192BIT_KEY_LEN = 24;
|
||||
COLIB_256BIT_KEY_LEN = 32;
|
||||
|
||||
// Error -----------------------------------------------------------------------
|
||||
// TCOLIB_ERROR = (
|
||||
COLIB_SUCCESS = 0;
|
||||
COLIB_ERROR_FATAL = 100;
|
||||
COLIB_ERROR_ALREADY_INIT = 101;
|
||||
COLIB_ERROR_UNSUPPORTED_MODE = 102;
|
||||
COLIB_ERROR_UNSUPPORTED_RSA_KEY = 103;
|
||||
COLIB_ERROR_FILE_OPEN = 104;
|
||||
COLIB_ERROR_FILE_READ = 105;
|
||||
COLIB_ERROR_CHANGE_STATE = 106;
|
||||
COLIB_ERROR_ALLOC = 107;
|
||||
COLIB_ERROR_ENTROPY = 108;
|
||||
COLIB_ERROR_SELFTEST_DRBG = 500;
|
||||
COLIB_ERROR_SELFTEST_BLOCK = 501;
|
||||
COLIB_ERROR_SELFTEST_HASH = 502;
|
||||
COLIB_ERROR_SELFTEST_ENTROPY = 503;
|
||||
COLIB_ERROR_SELFTEST_RSA = 504;
|
||||
COLIB_ERROR_SELFTEST_HMAC = 505;
|
||||
COLIB_ERROR_MOD_SIGN = 506;
|
||||
COLIB_ERROR_CRYPTO_BLOCK = 1000;
|
||||
COLIB_ERROR_CRYPTO_PAD = 1001;
|
||||
COLIB_ERROR_CRYPTO_INVALID_USERKEYLEN = 1002;
|
||||
COLIB_ERROR_CRYPTO_DATA_LEN = 1003;
|
||||
COLIB_ERROR_CRYPTO_CIPHER_LEN = 1004;
|
||||
COLIB_ERROR_CRYPTO_MODE = 1005;
|
||||
COLIB_ERROR_CRYPTO_SHA = 1500;
|
||||
COLIB_ERROR_CRYPTO_HMAC = 1600;
|
||||
COLIB_ERROR_DRBG = 2000;
|
||||
COLIB_ERROR_DRBG_SIZE_OVER = 2001;
|
||||
COLIB_ERROR_DRBG_BUFFER = 2002;
|
||||
COLIB_ERROR_DRBG_HASH_DF = 2003;
|
||||
COLIB_ERROR_DRBG_ADDITIONAL = 2004;
|
||||
COLIB_ERROR_DRBG_MEMORY = 2005;
|
||||
COLIB_ERROR_DRBG_HASHGEN = 2006;
|
||||
COLIB_ERROR_RSA = 3000;
|
||||
COLIB_ERROR_RSA_PUBLICKEY_FORMAT_ERROR = 3001;
|
||||
COLIB_ERROR_RSA_PRIVITEKEY_FORMAT_ERROR = 3002;
|
||||
COLIB_ERROR_RSA_INVALID_INPUT = 3003;
|
||||
COLIB_ERROR_RSA_INVALID_SIGNLEN = 3004;
|
||||
COLIB_ERROR_RSA_INVALID_PSSEM_LEN = 3005;
|
||||
COLIB_ERROR_RSA_INVALID_PSSEM_FORMAT = 3006;
|
||||
COLIB_ERROR_RSA_INVALID_DBMASK_FORMAT = 3007;
|
||||
COLIB_ERROR_RSA_FAIL_PSSVERIFY = 3008;
|
||||
COLIB_ERROR_RSA_INVALID_OAEP_FORMAT = 3009;
|
||||
COLIB_ERROR_RSA_INVALID_OAEP_HASH = 3010;
|
||||
COLIB_ERROR_RSA_MESSAGE_OUT_OF_RANGE = 3011;
|
||||
COLIB_ERROR_RSA_CIPHERTEXT_OUT_OF_RANGE = 3012;
|
||||
COLIB_ERROR_RSA_ENCMESSAGE_TOO_LONG = 3013;
|
||||
COLIB_ERROR_RSA_DECRYPTION = 3014;
|
||||
COLIB_ERROR_RSA_ENCODING = 3015;
|
||||
COLIB_ERROR_RSA_PUBLIC_OP = 3016;
|
||||
COLIB_ERROR_RSA_PRIVATE_OP = 3017;
|
||||
COLIB_ERROR_RSA_KEY_PAIR = 3018;
|
||||
COLIB_ERROR_RSA_FAIL_MALLOC = 3019;
|
||||
COLIB_ERROR_RSA_KEY_GEN = 3020;
|
||||
COLIB_ERROR_BN = 4000;
|
||||
// );
|
||||
type
|
||||
TCOLIB_MODE = (
|
||||
COLIB_MODE_APPROVE = 0,
|
||||
COLIB_MODE_SEED = 1,
|
||||
COLIB_MODE_ARIA,
|
||||
COLIB_MODE_SHA224 = 100,
|
||||
COLIB_MODE_SHA256,
|
||||
COLIB_MODE_SHA384,
|
||||
COLIB_MODE_SHA512,
|
||||
COLIB_MODE_HMAC,
|
||||
COLIB_MODE_HASH_DRBG = 200,
|
||||
COLIB_MODE_RSAES_OAEP = 300,
|
||||
COLIB_MODE_RSASSA_PSS,
|
||||
COLIB_MODE_DISAPPROVE = 10000,
|
||||
COLIB_MODE_AES = 10001,
|
||||
COLIB_MODE_MAX
|
||||
);
|
||||
TCOLIB_RSA_KEY = (
|
||||
COLIB_RSA_KEY_2048 = 2048
|
||||
);
|
||||
TCOLIB_BLOCK_CRYPTO_MODE = (
|
||||
BLOCK_CRYPTO_MODE_UNUSED = 0,
|
||||
BLOCK_CRYPTO_MODE_ECB = 1,
|
||||
BLOCK_CRYPTO_MODE_CBC = 2,
|
||||
BLOCK_CRYPTO_MODE_OFB = 3,
|
||||
BLOCK_CRYPTO_MODE_CFB = 4
|
||||
);
|
||||
TCOLIB_STATE = (
|
||||
COLIB_STATE_INIT = 1,
|
||||
COLIB_STATE_APPROVE,
|
||||
COLIB_STATE_DISAPPROVE,
|
||||
COLIB_STATE_FATAL_ERROR,
|
||||
COLIB_STATE_WARN_ERROR = 5,
|
||||
COLIB_STATE_SELFTEST,
|
||||
COLIB_STATE_INIT_DONE,
|
||||
COLIB_STATE_INIT_DOING
|
||||
);
|
||||
TCOLIB_ENC_TYPE = (
|
||||
ENC_TYPE_ENCRYPT = 0,
|
||||
ENC_TYPE_DECRYPT = 1
|
||||
);
|
||||
TCOLIB_PAD_TYPE = (
|
||||
COLIB_PAD_TYPE_UNUSED = 0,
|
||||
COLIB_PAD_TYPE_NO = 1,
|
||||
COLIB_PAD_TYPE_PKCS = 2
|
||||
);
|
||||
TCOLIB_KAT_STATE = (
|
||||
KAT_STATE_INIT = 0,
|
||||
KAT_STATE_DOING = 1,
|
||||
KAT_STATE_DONE = 2
|
||||
);
|
||||
TCOLIB_MODE_STATE = record
|
||||
seed_enc: TCOLIB_KAT_STATE;
|
||||
seed_dec: TCOLIB_KAT_STATE;
|
||||
aria_enc: TCOLIB_KAT_STATE;
|
||||
aria_dec: TCOLIB_KAT_STATE;
|
||||
sha: TCOLIB_KAT_STATE;
|
||||
hmac: TCOLIB_KAT_STATE;
|
||||
hash_drbg: TCOLIB_KAT_STATE;
|
||||
rsaes_oaep_enc: TCOLIB_KAT_STATE;
|
||||
rsaes_oaep_dec: TCOLIB_KAT_STATE;
|
||||
rsassa_pss_sign: TCOLIB_KAT_STATE;
|
||||
rsassa_pss_veri: TCOLIB_KAT_STATE;
|
||||
integrity: TCOLIB_KAT_STATE;
|
||||
end;
|
||||
|
||||
(*************** New Data Types *******************************************)
|
||||
UINT = Cardinal;
|
||||
COUWORD = Cardinal;
|
||||
UCHAR = Byte;
|
||||
SINT = Integer;
|
||||
PDWORD = ^DWORD;
|
||||
TMPZ = record
|
||||
sig : SINT; // 1:positive, 0:zero, -1:negative
|
||||
dat : PDWORD; // Max 104 WORD = 104 * 32 = 3328 bit
|
||||
len : SINT;
|
||||
end;
|
||||
PCOKEY = ^TCOKEY;
|
||||
TCOKEY = record
|
||||
bits : UINT;
|
||||
ktype : UCHAR; // pri 0, pub 1
|
||||
p : TMPZ; // 1st prime factor
|
||||
q : TMPZ; // 2nd prime factor
|
||||
e : TMPZ; // public exponent
|
||||
n : TMPZ; // public modulus
|
||||
d : TMPZ; // private exponent
|
||||
dp : TMPZ; // d % (p - 1)
|
||||
dq : TMPZ; // d % (q - 1)
|
||||
qp : TMPZ; // 1 / (Q % P)
|
||||
end;
|
||||
PCOKEY_BUF = ^TCOKEY_BUF;
|
||||
TCOKEY_BUF = record
|
||||
p_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
q_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
e_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
n_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
d_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
dp_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
dq_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
qp_dat : array[0..MPZ_WORD_LEN - 1] of COUWORD;
|
||||
end;
|
||||
// For RSA Hash Fucntion. This is all hash func of CUBEONE
|
||||
TCORSA_HASH_TYPE = (
|
||||
HASH_SHA256
|
||||
);
|
||||
TCORSA_KEY_TYPE = (
|
||||
COKEY_TYPE_PRIVATE = 0,
|
||||
COKEY_TYPE_PUBLIC = 1
|
||||
);
|
||||
PCIPHER_INFO = ^TCIPHER_INFO;
|
||||
TCIPHER_INFO = record
|
||||
colib_mode : Integer;
|
||||
colib_block_crypto_mode : Integer;//TCOLIB_BLOCK_CRYPTO_MODE;
|
||||
colib_pad_type : Integer;//TCOLIB_PAD_TYPE;
|
||||
user_key : PBYTE;
|
||||
user_key_len : UINT;
|
||||
iv : PBYTE;
|
||||
iv_len : UINT;
|
||||
input : PBYTE;
|
||||
input_len : UINT;
|
||||
output : PBYTE;
|
||||
output_len : PUINT;
|
||||
end;
|
||||
PRSA_INFO = ^TRSA_INFO;
|
||||
TRSA_INFO = record
|
||||
cokey : PCOKEY;
|
||||
colib_mode : Integer;
|
||||
rsa_hash_type : TCORSA_HASH_TYPE;
|
||||
input : PBYTE;
|
||||
input_len : UINT;
|
||||
output : PBYTE;
|
||||
output_len : PUINT;
|
||||
salt : PBYTE;
|
||||
salt_len : UINT;
|
||||
end;
|
||||
PCOLIB_VERSION = ^TCOLIB_VERSION;
|
||||
TCOLIB_VERSION = record
|
||||
name : array[0..5] of AnsiChar;
|
||||
major : Integer;
|
||||
minor : Integer;
|
||||
build : Integer;
|
||||
version_str : array[0..255] of AnsiChar;
|
||||
end;
|
||||
|
||||
TCOLibSetCipherInfo = procedure(cipher_info: PCIPHER_INFO; colib_mode, colib_block_crypto_mode,
|
||||
colib_pad_type: Integer; user_key: PBYTE; user_key_len: UINT;
|
||||
iv: PBYTE; iv_len: UINT; input: PBYTE; input_len: UINT; output:
|
||||
PBYTE; output_len: PUINT); stdcall;
|
||||
// TCOLibInitCipherInfo = procedure(cipher_info: PCIPHER_INFO); stdcall; // DLL에 함수 없음, TCOLibZeroCipherInfo()로 대체 된듯
|
||||
TCOLibSetRsaInfo = procedure(rsa_info: PRSA_INFO; cokey: PCOKEY; colib_mode: Integer;
|
||||
rsa_hash_type: TCORSA_HASH_TYPE; input: PBYTE; input_len: UINT;
|
||||
output: PBYTE; output_len: PUINT; salt: PBYTE; salt_len: UINT); stdcall;
|
||||
// TCOLibInitRsaInfo = procedure(rsa_info: PRSA_INFO); stdcall; // DLL에 함수 없음, TCOLibZeroRsaInfo()로 대체 된듯
|
||||
TCOLibGetState = function: Integer; stdcall;
|
||||
TCOLibGetVersion = function(colib_version: PCOLIB_VERSION): Integer; stdcall;
|
||||
TCOLibSelfTestAll = function: Integer; stdcall;
|
||||
TCOLibEncrypt = function(cipher_info: PCIPHER_INFO): Integer; stdcall;
|
||||
TCOLibDecrypt = function(cipher_info: PCIPHER_INFO): Integer; stdcall;
|
||||
TCOLibGetKey = function(key: PBYTE; key_len: UINT): Integer; stdcall;
|
||||
TCOLibDrbg = function(buf: PBYTE; buf_len: UINT; addtl: PBYTE; addtl_len: UINT; pers: PBYTE; pers_len: UINT; pr: SINT): Integer; stdcall;
|
||||
TCOLibEncryptRsa = function(rsa_info: PRSA_INFO): Integer; stdcall;
|
||||
TCOLibDecryptRsa = function(rsa_info: PRSA_INFO): Integer; stdcall;
|
||||
TCOLibGetRsaKey = function(bits: Integer; prk, puk: PCOKEY): Integer; stdcall;
|
||||
TCOLibRsaKeyInit = function(cokey: PCOKEY; cokey_buf: PCOKEY_BUF): Integer; stdcall;
|
||||
TCOLibGetModeState = procedure(colib_mode_state: PInteger); stdcall;
|
||||
|
||||
TCOLibZeroCipherInfo = procedure(cipher_info: PCIPHER_INFO); stdcall;
|
||||
TCOLibZeroRsaInfo = procedure(rsa_info: PRSA_INFO); stdcall;
|
||||
|
||||
TCOLibGetErrorStr = function(colib_error: Integer): PAnsiChar; stdcall;
|
||||
TCOLibGetModeStr = function(colib_mode: TCOLIB_MODE): PAnsiChar; stdcall;
|
||||
TCOLibGetStateStr = function(colib_state: TCOLIB_STATE): PAnsiChar; stdcall;
|
||||
TCOLibGetKatStateStr = function(colib_kat_state: TCOLIB_KAT_STATE): PAnsiChar; stdcall;
|
||||
|
||||
procedure COLibSetCipherInfo(cipher_info: PCIPHER_INFO; colib_mode: TCOLIB_MODE; colib_block_crypto_mode: TCOLIB_BLOCK_CRYPTO_MODE;
|
||||
colib_pad_type: TCOLIB_PAD_TYPE; user_key: PBYTE; user_key_len: UINT;
|
||||
iv: PBYTE; iv_len: UINT; input: PBYTE; input_len: UINT;
|
||||
output: PBYTE; output_len: PUINT);
|
||||
procedure COLibSetRsaInfo(rsa_info: PRSA_INFO; cokey: PCOKEY; colib_mode: Integer;
|
||||
rsa_hash_type: TCORSA_HASH_TYPE; input: PBYTE; input_len: UINT;
|
||||
output: PBYTE; output_len: PUINT; salt: PBYTE; salt_len: UINT);
|
||||
function COLibGetState: Integer;
|
||||
function COLibGetVersion(colib_version: PCOLIB_VERSION): Integer;
|
||||
function COLibSelfTestAll: Integer;
|
||||
function COLibEncrypt(cipher_info: PCIPHER_INFO): Integer;
|
||||
function COLibDecrypt(cipher_info: PCIPHER_INFO): Integer;
|
||||
function COLibGetKey(key: PBYTE; key_len: UINT): Integer;
|
||||
function COLibDrbg(buf: PBYTE; buf_len: UINT; addtl: PBYTE; addtl_len: UINT;
|
||||
pers: PBYTE; pers_len: UINT; pr: SINT): Integer;
|
||||
function COLibEncryptRsa(rsa_info: PRSA_INFO): Integer;
|
||||
function COLibDecryptRsa(rsa_info: PRSA_INFO): Integer;
|
||||
function COLibGetRsaKey(bits: Integer; prk, puk: PCOKEY): Integer;
|
||||
function COLibRsaKeyInit(cokey: PCOKEY; cokey_buf: PCOKEY_BUF): Integer;
|
||||
procedure COLibGetModeState(colib_mode_state: PInteger);
|
||||
|
||||
procedure COLibZeroCipherInfo(cipher_info: PCIPHER_INFO);
|
||||
procedure COLibZeroRsaInfo(rsa_info: PRSA_INFO);
|
||||
|
||||
function COLibGetErrorStr(colib_error: Integer): PAnsiChar;
|
||||
function COLibGetModeStr(colib_mode: TCOLIB_MODE): PAnsiChar;
|
||||
function COLibGetStateStr(colib_state: TCOLIB_STATE): PAnsiChar;
|
||||
function COLibGetKatStateStr(colib_kat_state: TCOLIB_KAT_STATE): PAnsiChar;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Tocsg.Path, Tocsg.Trace;
|
||||
|
||||
var
|
||||
_hCoLib: THandle = 0;
|
||||
_fnCOLibSetCipherInfo: TCOLibSetCipherInfo = nil;
|
||||
// _fnCOLibInitCipherInfo: TCOLibInitCipherInfo = nil;
|
||||
_fnCOLibSetRsaInfo: TCOLibSetRsaInfo = nil;
|
||||
// _fnCOLibInitRsaInfo: TCOLibInitRsaInfo = nil;
|
||||
_fnCOLibGetState: TCOLibGetState = nil;
|
||||
_fnCOLibGetVersion: TCOLibGetVersion = nil;
|
||||
_fnCOLibSelfTestAll: TCOLibSelfTestAll = nil;
|
||||
_fnCOLibEncrypt: TCOLibEncrypt = nil;
|
||||
_fnCOLibDecrypt: TCOLibDecrypt = nil;
|
||||
_fnCOLibGetKey: TCOLibGetKey = nil;
|
||||
_fnCOLibDrbg: TCOLibDrbg = nil;
|
||||
_fnCOLibEncryptRsa: TCOLibEncryptRsa = nil;
|
||||
_fnCOLibDecryptRsa: TCOLibDecryptRsa = nil;
|
||||
_fnCOLibGetRsaKey: TCOLibGetRsaKey = nil;
|
||||
_fnCOLibRsaKeyInit: TCOLibRsaKeyInit = nil;
|
||||
_fnCOLibGetModeState: TCOLibGetModeState = nil;
|
||||
_fnCOLibZeroCipherInfo: TCOLibZeroCipherInfo = nil;
|
||||
_fnCOLibZeroRsaInfo: TCOLibZeroRsaInfo = nil;
|
||||
_fnCOLibGetErrorStr: TCOLibGetErrorStr = nil;
|
||||
_fnCOLibGetModeStr: TCOLibGetModeStr = nil;
|
||||
_fnCOLibGetStateStr: TCOLibGetStateStr = nil;
|
||||
_fnCOLibGetKatStateStr: TCOLibGetKatStateStr = nil;
|
||||
|
||||
function InitCOLibProcedure: Boolean;
|
||||
var
|
||||
sPath: String;
|
||||
begin
|
||||
if _hCoLib = 0 then
|
||||
begin
|
||||
sPath := GetRunExePathDir + DLL_COLIB;
|
||||
if not FileExists(sPath) then
|
||||
begin
|
||||
TTgTrace.T('Fail .. InitCOLibProcedure() .. Not found DLL, Path=%s', [sPath]);
|
||||
Exit(false);
|
||||
end;
|
||||
|
||||
_hCoLib := LoadLibrary(PChar(sPath));
|
||||
if _hCoLib <> 0 then
|
||||
begin
|
||||
@_fnCOLibSetCipherInfo := GetProcAddress(_hCoLib, 'COLibSetCipherInfo');
|
||||
ASSERT(@_fnCOLibSetCipherInfo <> nil);
|
||||
// @_fnCOLibInitCipherInfo := GetProcAddress(_hCoLib, 'COLibInitCipherInfo');
|
||||
// ASSERT(@_fnCOLibInitCipherInfo <> nil);
|
||||
@_fnCOLibSetRsaInfo := GetProcAddress(_hCoLib, 'COLibSetRsaInfo');
|
||||
ASSERT(@_fnCOLibSetRsaInfo <> nil);
|
||||
// @_fnCOLibInitRsaInfo := GetProcAddress(_hCoLib, 'COLibInitRsaInfo');
|
||||
// ASSERT(@_fnCOLibInitRsaInfo <> nil);
|
||||
@_fnCOLibGetState := GetProcAddress(_hCoLib, 'COLibGetState');
|
||||
ASSERT(@_fnCOLibGetState <> nil);
|
||||
@_fnCOLibGetVersion := GetProcAddress(_hCoLib, 'COLibGetVersion');
|
||||
ASSERT(@_fnCOLibGetVersion <> nil);
|
||||
@_fnCOLibSelfTestAll := GetProcAddress(_hCoLib, 'COLibSelfTestAll');
|
||||
ASSERT(@_fnCOLibSelfTestAll <> nil);
|
||||
@_fnCOLibEncrypt := GetProcAddress(_hCoLib, 'COLibEncrypt');
|
||||
ASSERT(@_fnCOLibEncrypt <> nil);
|
||||
@_fnCOLibDecrypt := GetProcAddress(_hCoLib, 'COLibDecrypt');
|
||||
ASSERT(@_fnCOLibDecrypt <> nil);
|
||||
@_fnCOLibGetKey := GetProcAddress(_hCoLib, 'COLibGetKey');
|
||||
ASSERT(@_fnCOLibGetKey <> nil);
|
||||
@_fnCOLibDrbg := GetProcAddress(_hCoLib, 'COLibDrbg');
|
||||
ASSERT(@_fnCOLibDrbg <> nil);
|
||||
@_fnCOLibEncryptRsa := GetProcAddress(_hCoLib, 'COLibEncryptRsa');
|
||||
ASSERT(@_fnCOLibEncryptRsa <> nil);
|
||||
@_fnCOLibDecryptRsa := GetProcAddress(_hCoLib, 'COLibDecryptRsa');
|
||||
ASSERT(@_fnCOLibDecryptRsa <> nil);
|
||||
@_fnCOLibGetRsaKey := GetProcAddress(_hCoLib, 'COLibGetRsaKey');
|
||||
ASSERT(@_fnCOLibGetRsaKey <> nil);
|
||||
@_fnCOLibRsaKeyInit := GetProcAddress(_hCoLib, 'COLibRsaKeyInit');
|
||||
ASSERT(@_fnCOLibRsaKeyInit <> nil);
|
||||
@_fnCOLibGetModeState := GetProcAddress(_hCoLib, 'COLibGetModeState');
|
||||
ASSERT(@_fnCOLibGetModeState <> nil);
|
||||
@_fnCOLibZeroCipherInfo := GetProcAddress(_hCoLib, 'COLibZeroCipherInfo');
|
||||
ASSERT(@_fnCOLibZeroCipherInfo <> nil);
|
||||
@_fnCOLibZeroRsaInfo := GetProcAddress(_hCoLib, 'COLibZeroRsaInfo');
|
||||
ASSERT(@_fnCOLibZeroRsaInfo <> nil);
|
||||
|
||||
@_fnCOLibGetErrorStr := GetProcAddress(_hCoLib, 'COLibGetErrorStr');
|
||||
ASSERT(@_fnCOLibGetErrorStr <> nil);
|
||||
@_fnCOLibGetModeStr := GetProcAddress(_hCoLib, 'COLibGetModeStr');
|
||||
ASSERT(@_fnCOLibGetModeStr <> nil);
|
||||
@_fnCOLibGetStateStr := GetProcAddress(_hCoLib, 'COLibGetStateStr');
|
||||
ASSERT(@_fnCOLibGetStateStr <> nil);
|
||||
@_fnCOLibGetKatStateStr := GetProcAddress(_hCoLib, 'COLibGetKatStateStr');
|
||||
ASSERT(@_fnCOLibGetKatStateStr <> nil);
|
||||
end;
|
||||
end;
|
||||
Result := _hCoLib <> 0;
|
||||
end;
|
||||
|
||||
procedure COLibSetCipherInfo(cipher_info: PCIPHER_INFO; colib_mode: TCOLIB_MODE; colib_block_crypto_mode: TCOLIB_BLOCK_CRYPTO_MODE;
|
||||
colib_pad_type: TCOLIB_PAD_TYPE; user_key: PBYTE; user_key_len: UINT;
|
||||
iv: PBYTE; iv_len: UINT; input: PBYTE; input_len: UINT;
|
||||
output: PBYTE; output_len: PUINT);
|
||||
begin
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibSetCipherInfo) then
|
||||
_fnCOLibSetCipherInfo(cipher_info, Integer(colib_mode), Integer(colib_block_crypto_mode),
|
||||
Integer(colib_pad_type), user_key, user_key_len,
|
||||
iv, iv_len, input, input_len, output, output_len);
|
||||
end;
|
||||
|
||||
procedure COLibSetRsaInfo(rsa_info: PRSA_INFO; cokey: PCOKEY; colib_mode: Integer;
|
||||
rsa_hash_type: TCORSA_HASH_TYPE; input: PBYTE; input_len: UINT;
|
||||
output: PBYTE; output_len: PUINT; salt: PBYTE; salt_len: UINT);
|
||||
begin
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibSetRsaInfo) then
|
||||
_fnCOLibSetRsaInfo(rsa_info, cokey, colib_mode, rsa_hash_type, input, input_len,
|
||||
output, output_len, salt, salt_len);
|
||||
end;
|
||||
|
||||
function COLibGetState: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetState) then
|
||||
Result := _fnCOLibGetState;
|
||||
end;
|
||||
|
||||
function COLibGetVersion(colib_version: PCOLIB_VERSION): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetVersion) then
|
||||
Result := _fnCOLibGetVersion(colib_version);
|
||||
end;
|
||||
|
||||
function COLibSelfTestAll: Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibSelfTestAll) then
|
||||
Result := _fnCOLibSelfTestAll;
|
||||
end;
|
||||
|
||||
function COLibEncrypt(cipher_info: PCIPHER_INFO): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibEncrypt) then
|
||||
Result := _fnCOLibEncrypt(cipher_info);
|
||||
end;
|
||||
|
||||
function COLibDecrypt(cipher_info: PCIPHER_INFO): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibDecrypt) then
|
||||
Result := _fnCOLibDecrypt(cipher_info);
|
||||
end;
|
||||
|
||||
function COLibGetKey(key: PBYTE; key_len: UINT): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetKey) then
|
||||
Result := _fnCOLibGetKey(key, key_len);
|
||||
end;
|
||||
|
||||
function COLibDrbg(buf: PBYTE; buf_len: UINT; addtl: PBYTE; addtl_len: UINT;
|
||||
pers: PBYTE; pers_len: UINT; pr: SINT): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibDrbg) then
|
||||
Result := _fnCOLibDrbg(buf, buf_len, addtl, addtl_len, pers, pers_len, pr);
|
||||
end;
|
||||
|
||||
function COLibEncryptRsa(rsa_info: PRSA_INFO): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibEncryptRsa) then
|
||||
Result := _fnCOLibEncryptRsa(rsa_info);
|
||||
end;
|
||||
|
||||
function COLibDecryptRsa(rsa_info: PRSA_INFO): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibDecryptRsa) then
|
||||
Result := _fnCOLibDecryptRsa(rsa_info);
|
||||
end;
|
||||
|
||||
function COLibGetRsaKey(bits: Integer; prk, puk: PCOKEY): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetRsaKey) then
|
||||
Result := _fnCOLibGetRsaKey(bits, prk, puk);
|
||||
end;
|
||||
|
||||
function COLibRsaKeyInit(cokey: PCOKEY; cokey_buf: PCOKEY_BUF): Integer;
|
||||
begin
|
||||
Result := -1;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibRsaKeyInit) then
|
||||
Result := _fnCOLibRsaKeyInit(cokey, cokey_buf);
|
||||
end;
|
||||
|
||||
procedure COLibGetModeState(colib_mode_state: PInteger);
|
||||
begin
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetModeState) then
|
||||
_fnCOLibGetModeState(colib_mode_state);
|
||||
end;
|
||||
|
||||
procedure COLibZeroCipherInfo(cipher_info: PCIPHER_INFO);
|
||||
begin
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibZeroCipherInfo) then
|
||||
_fnCOLibZeroCipherInfo(cipher_info);
|
||||
end;
|
||||
|
||||
procedure COLibZeroRsaInfo(rsa_info: PRSA_INFO);
|
||||
begin
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibZeroRsaInfo) then
|
||||
_fnCOLibZeroRsaInfo(rsa_info);
|
||||
end;
|
||||
|
||||
function COLibGetErrorStr(colib_error: Integer): PAnsiChar;
|
||||
begin
|
||||
Result := nil;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetErrorStr) then
|
||||
Result := _fnCOLibGetErrorStr(colib_error);
|
||||
end;
|
||||
|
||||
function COLibGetModeStr(colib_mode: TCOLIB_MODE): PAnsiChar;
|
||||
begin
|
||||
Result := nil;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetModeStr) then
|
||||
Result := _fnCOLibGetModeStr(colib_mode);
|
||||
end;
|
||||
function COLibGetStateStr(colib_state: TCOLIB_STATE): PAnsiChar;
|
||||
begin
|
||||
Result := nil;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetStateStr) then
|
||||
Result := _fnCOLibGetStateStr(colib_state);
|
||||
end;
|
||||
function COLibGetKatStateStr(colib_kat_state: TCOLIB_KAT_STATE): PAnsiChar;
|
||||
begin
|
||||
Result := nil;
|
||||
if InitCOLibProcedure and Assigned(_fnCOLibGetKatStateStr) then
|
||||
Result := _fnCOLibGetKatStateStr(colib_kat_state);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -13,7 +13,7 @@ interface
|
|||
uses
|
||||
Tocsg.Thread, System.SysUtils, System.Classes, Winapi.Windows,
|
||||
Winapi.Messages, System.Generics.Collections, CttSchDefine, Tocsg.KvFilter,
|
||||
ManagerPattern, Tocsg.Fasoo, Tocsg.Win32;
|
||||
ManagerPattern, Tocsg.Fasoo, Tocsg.Win32, vcl.Dialogs;
|
||||
|
||||
const
|
||||
LOG_FS_DEC_FAIL = 'FsDecFail.log';
|
||||
|
|
@ -52,7 +52,7 @@ uses
|
|||
Tocsg.Shell, superobject, ProcessSoftcampDRM, Tocsg.Hash, Tocsg.FileInfo,
|
||||
Tocsg.Convert, Tocsg.Registry, Condition, Tocsg.AIP, GlobalDefine,
|
||||
Winapi.ActiveX, Tocsg.Kess, Tocsg.Fasoo.Global.Define, Tocsg.Fasoo.Global,
|
||||
Tocsg.Valid, Tocsg.Trace;
|
||||
Tocsg.Valid, Tocsg.Trace, Tocsg.COLib.Encrypt;
|
||||
|
||||
{ TThdCttSch }
|
||||
|
||||
|
|
@ -291,13 +291,14 @@ var
|
|||
end;
|
||||
end;
|
||||
|
||||
// [yhkim]
|
||||
function EncFile(sPath: String): Boolean;
|
||||
var
|
||||
enc: TTgDrmEnc;
|
||||
sEncPath: String;
|
||||
pKek, pDek: TBytes;
|
||||
begin
|
||||
Result := false;
|
||||
|
||||
try
|
||||
if not ForceDirectories(sEncDir) then
|
||||
exit;
|
||||
|
|
@ -349,25 +350,70 @@ var
|
|||
exit;
|
||||
|
||||
// if not MoveFile_wait(sPath, sEncPath, 3) then
|
||||
if not CopyFile(PChar(sPath), PChar(sEncPath), false) then
|
||||
exit;
|
||||
DeleteFile(PChar(sPath));
|
||||
SaveStrToFile(sEncPath + '.i', sPath, TEncoding.UTF8);
|
||||
// if not CopyFile(PChar(sPath), PChar(sEncPath), false) then
|
||||
// exit;
|
||||
// DeleteFile(PChar(sPath));
|
||||
// SaveStrToFile(sEncPath + '.i', sPath, TEncoding.UTF8);
|
||||
//
|
||||
// Guard(enc, TTgDrmEnc.Create(sPath));
|
||||
//
|
||||
// enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo, sHost, sDept, sPoName, dwCsType);
|
||||
// if enc.EncryptFromFile(sPass, sEncPath) then
|
||||
// begin
|
||||
// DeleteFile(PChar(sEncPath));
|
||||
// DeleteFile(PChar(sEncPath + '.i'));
|
||||
// Result := true;
|
||||
// end else begin
|
||||
//// MoveFile_wait(sEncPath, sPath, 3);
|
||||
// if CopyFile(PChar(sEncPath), PChar(sPath), false) then
|
||||
// DeleteFile(PChar(sEncPath));
|
||||
// DeleteFile(PChar(sEncPath + '.i'));
|
||||
// end;
|
||||
|
||||
Guard(enc, TTgDrmEnc.Create(sPath));
|
||||
|
||||
enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo, sHost, sDept, sPoName, dwCsType);
|
||||
if enc.EncryptFromFile(sPass, sEncPath) then
|
||||
// [yhkim]
|
||||
// 이미 암호화된 파일이면 중단
|
||||
if TTgColibDrm.IsEncrypt(sPath) then
|
||||
begin
|
||||
DeleteFile(PChar(sEncPath));
|
||||
DeleteFile(PChar(sEncPath + '.i'));
|
||||
Result := true;
|
||||
end else begin
|
||||
// MoveFile_wait(sEncPath, sPath, 3);
|
||||
if CopyFile(PChar(sEncPath), PChar(sPath), false) then
|
||||
DeleteFile(PChar(sEncPath));
|
||||
DeleteFile(PChar(sEncPath + '.i'));
|
||||
//ShowMessage('이미 암호화된 파일입니다. 암호화를 중단합니다');
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
||||
pKek := TTgColibDrm.GetKEK('kek.bin');
|
||||
if pKek = nil then
|
||||
exit;
|
||||
|
||||
pDek := TTgColibDrm.GetDEK('dek.bin', pKek);
|
||||
if pDek = nil then
|
||||
exit;
|
||||
|
||||
ShowMessage('암호화 대상: ' +sPath);
|
||||
|
||||
try
|
||||
TTgColibDrm.DoEncrypt(sPath, pDek);
|
||||
|
||||
// 암호화 결과 파일이 정상적으로 생성되었는지 확인
|
||||
if FileExists(sPath + '.enc') then
|
||||
begin
|
||||
// 성공 시 원본 파일을 삭제하고 암호화된 파일을 원본 이름으로 변경
|
||||
if DeleteFile(PChar(sPath)) then
|
||||
begin
|
||||
if MoveFile_wait(sPath + '.enc', sPath, 3) then
|
||||
Result := True;
|
||||
end;
|
||||
end;
|
||||
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
ETgException.TraceException(Self, E, '암호화 실패: ' + sPath);
|
||||
// 실패 시 찌꺼기 파일 제거
|
||||
if FileExists(sPath + '.enc') then
|
||||
DeleteFile(PChar(sPath + '.enc'));
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,57 @@
|
|||
object AuthForm: TAuthForm
|
||||
Left = 0
|
||||
Top = 0
|
||||
BorderIcons = [biMinimize, biMaximize]
|
||||
Caption = 'BSOne Login'
|
||||
ClientHeight = 171
|
||||
ClientWidth = 146
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -12
|
||||
Font.Name = 'Segoe UI'
|
||||
Font.Style = []
|
||||
OnCreate = FormCreate
|
||||
TextHeight = 15
|
||||
object Label1: TLabel
|
||||
Left = 8
|
||||
Top = 8
|
||||
Width = 11
|
||||
Height = 15
|
||||
Caption = 'ID'
|
||||
end
|
||||
object Label2: TLabel
|
||||
Left = 8
|
||||
Top = 58
|
||||
Width = 18
|
||||
Height = 15
|
||||
Caption = 'PW'
|
||||
end
|
||||
object EditID: TEdit
|
||||
Left = 8
|
||||
Top = 29
|
||||
Width = 129
|
||||
Height = 23
|
||||
TabOrder = 0
|
||||
TextHint = 'ID'#47484' '#51077#47141#54616#49464#50836
|
||||
end
|
||||
object EditPW: TEdit
|
||||
Left = 8
|
||||
Top = 79
|
||||
Width = 129
|
||||
Height = 23
|
||||
PasswordChar = '*'
|
||||
TabOrder = 1
|
||||
TextHint = #54056#49828#50892#46300#47484' '#51077#47141#54616#49464#50836
|
||||
end
|
||||
object ButtonLogin: TButton
|
||||
Left = 8
|
||||
Top = 120
|
||||
Width = 129
|
||||
Height = 33
|
||||
Caption = 'Login'
|
||||
Default = True
|
||||
TabOrder = 2
|
||||
OnClick = ButtonLoginClick
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
unit UserAuthentification;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
|
||||
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
|
||||
superobject, IdHTTP, IdSSLOpenSSL, System.Math, System.IOUtils, System.RegularExpressions,
|
||||
Tocsg.Safe, Tocsg.COLib, Tocsg.COLib.Encrypt;
|
||||
|
||||
const
|
||||
CODE_AUTH_OK = 100;
|
||||
|
||||
type
|
||||
// 로그인 성공 시 호출될 이벤트 타입 정의
|
||||
TNotifyLoginSuccess = procedure(Sender: TObject; ResultCode: Integer) of object;
|
||||
|
||||
TAuthForm = class(TForm)
|
||||
Label1, Label2: TLabel;
|
||||
EditID, EditPW: TEdit;
|
||||
ButtonLogin: TButton;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure ButtonLoginClick(Sender: TObject);
|
||||
|
||||
private
|
||||
{ Private declarations }
|
||||
iFailCount: Integer; // 로그인 실패 횟수
|
||||
BlockStartTime: TDateTime; // 차단 시작 시간
|
||||
FOnSuccess: TNotifyLoginSuccess; // 이벤트를 담을 변수
|
||||
public
|
||||
{ Public declarations }
|
||||
sAgentId, sDestIPort: string;
|
||||
property OnSuccess: TNotifyLoginSuccess read FOnSuccess write FOnSuccess;
|
||||
end;
|
||||
|
||||
var
|
||||
AuthForm: TAuthForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
procedure TAuthForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
Self.Position := poScreenCenter;
|
||||
Self.BorderStyle := bsSingle;
|
||||
Self.FormStyle := fsStayOnTop;
|
||||
end;
|
||||
|
||||
function IsValidInput(const AText: string): Boolean;
|
||||
const
|
||||
// 영문, 숫자, 특수문자만 허용
|
||||
ALLOWED_PATTERN = '^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{};'':"\\|,.<>\/?]+$';
|
||||
begin
|
||||
// 빈 값 체크 후 패턴 검사
|
||||
Result := (AText <> '') and TRegEx.IsMatch(AText, ALLOWED_PATTERN);
|
||||
end;
|
||||
|
||||
function GetPostData(sDestIPort, sUrl, sData: String; sReqType: String = ''): String;
|
||||
var
|
||||
HTTP: TIdHTTP;
|
||||
SSL: TIdSSLIOHandlerSocketOpenSSL;
|
||||
ss: TStringStream;
|
||||
begin
|
||||
Result := '';
|
||||
|
||||
try
|
||||
if sUrl = '' then
|
||||
exit;
|
||||
|
||||
if sUrl[1] = '/' then
|
||||
Delete(sUrl, 1, 1);
|
||||
|
||||
Guard(SSL, TIdSSLIOHandlerSocketOpenSSL.Create(nil));
|
||||
SSL.SSLOptions.Method := sslvSSLv23;
|
||||
SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1];
|
||||
|
||||
Guard(HTTP, TIdHTTP.Create(nil));
|
||||
HTTP.IOHandler := SSL;
|
||||
with HTTP do
|
||||
begin
|
||||
HandleRedirects := true;
|
||||
Request.Clear;
|
||||
Request.UserAgent := 'Mozilla/5.0';
|
||||
Request.ContentType := 'application/xml';
|
||||
Request.AcceptCharSet := 'UTF-8';
|
||||
// Request.Connection := 'Keep-Alive';
|
||||
// Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100';
|
||||
Request.Connection := 'close';
|
||||
HTTPOptions := HTTPOptions - [hoKeepOrigProtocol];
|
||||
if sReqType <> '' then
|
||||
Request.CustomHeaders.Values['requestType'] := sReqType;
|
||||
HTTPOptions := HTTP.HTTPOptions + [hoForceEncodeParams];
|
||||
ConnectTimeout := 5000;
|
||||
ReadTimeout := 5000;
|
||||
end;
|
||||
|
||||
Guard(ss, TStringStream.Create(sData, TEncoding.UTF8));
|
||||
Result := HTTP.Post(sDestIPort + sUrl, ss);
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
//ShowMessage('HTTP 통신 내부 오류: ' + E.Message);
|
||||
Result := '';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TAuthForm.ButtonLoginClick(Sender: TObject);
|
||||
var
|
||||
O: ISuperObject;
|
||||
pSalt, pKek, pDek : TBytes;
|
||||
sResult, sSalt: String;
|
||||
nResult: integer;
|
||||
CurrentTime: TDateTime;
|
||||
begin
|
||||
|
||||
if iFailCount >= 5 then
|
||||
begin
|
||||
CurrentTime := Now;
|
||||
// 차단 시작 시간으로부터 5분이 지났는지 확인
|
||||
if (CurrentTime - BlockStartTime) < (5 / (24 * 60)) then
|
||||
begin
|
||||
MessageBox(0,'로그인 5회 실패로 인해 5분간 로그인이 차단됩니다', 'BSOne Login', MB_ICONINFORMATION);
|
||||
Exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// 5분이 지났으면 카운트 초기화
|
||||
iFailCount := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
if EditID.Text = '' then
|
||||
begin
|
||||
MessageBox(0,'ID를 입력하세요', 'BSOne Login', MB_ICONINFORMATION);
|
||||
EditID.SetFocus;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not IsValidInput(EditID.Text) then
|
||||
begin
|
||||
MessageBox(0,'ID에는 영문, 숫자, 특수기호를 제외하고 들어갈 수 없습니다', 'BSOne Login', MB_ICONINFORMATION);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if EditPW.Text = '' then
|
||||
begin
|
||||
MessageBox(0,'패스워드를 입력하세요', 'BSOne Login', MB_ICONINFORMATION);
|
||||
EditPW.SetFocus;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not IsValidInput(EditPW.Text) then
|
||||
begin
|
||||
MessageBox(0,'패스워드에는 영문, 숫자, 특수기호를 제외하고 들어갈 수 없습니다', 'BSOne Login', MB_ICONINFORMATION);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
try
|
||||
O := SO;
|
||||
// O.S['empId'] := '0505';
|
||||
// O.S['pw'] := 'Q!w2e3r4t5';
|
||||
// O.S['agentId'] := '25111809085600FF96644E47';
|
||||
O.S['empId'] := EditID.Text;
|
||||
O.S['pw'] := EditPW.Text;
|
||||
O.S['agentId'] := sAgentId;
|
||||
|
||||
sResult := GetPostData(sDestIPort, 'aapi/auth/refresh-token/issue', O.AsJSon);
|
||||
if sResult <> '' then
|
||||
begin
|
||||
if sResult.Contains('error') then
|
||||
begin
|
||||
//_Trace('Error .. GetRegPerInfoUrl() .. Msg="%s"', [Result]);
|
||||
ShowMessage('에러 1: '+ sResult);
|
||||
exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
O := SO(sResult);
|
||||
//O.S['refreshToken']
|
||||
iFailCount := 0;
|
||||
//ShowMessage('인증 완료');
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
Inc(iFailCount);
|
||||
|
||||
if iFailCount >= 5 then
|
||||
begin
|
||||
BlockStartTime := Now; // 현재 시간 기록
|
||||
ShowMessage('인증 실패 5회 연속으로 5분간 로그인이 차단됩니다.');
|
||||
exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
ShowMessage(Format('아이디 또는 비밀번호가 일치하지 않습니다. (현재 %d회 실패 / 5회 연속실패 시 차단)', [iFailCount]));
|
||||
end;
|
||||
exit;
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
ShowMessage('오류 발생: Fail .. GetRegPerInfoUrl()' + sLineBreak + E.Message);
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
// salt 생성
|
||||
pSalt := TTgColibDrm.CreateSalt(COLIB_128BIT_KEY_LEN);
|
||||
if pSalt = nil then
|
||||
begin
|
||||
ShowMessage('CreateSalt is failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
for var i := 0 to COLIB_128BIT_KEY_LEN - 1 do
|
||||
sSalt := sSalt + Format('%.2x', [pSalt[i]]);
|
||||
//ShowMessage('Salt : ' + sSalt);
|
||||
|
||||
// KEK 생성 및 암호화(사용자 로그인 계정 암호)
|
||||
pKek := TTgColibDrm.CreateKEK(EditPW.Text, sSalt, 1000, SHA256_DIGEST_SIZE);
|
||||
if pKek = nil then
|
||||
begin
|
||||
ShowMessage('CreateKEK is failed');
|
||||
exit;
|
||||
end;
|
||||
|
||||
// KEK 복호화 디버그
|
||||
// var pTemp := TTgColibDrm.GetKEK('kek.bin');
|
||||
// if (Length(pKek) = Length(pTemp)) and
|
||||
// CompareMem(@pKek[0], @pTemp[0], Length(pKek)) then
|
||||
// begin
|
||||
// ShowMessage('KEK 복호화 성공');
|
||||
// end;
|
||||
|
||||
// DEK 생성 및 암호화(KEK)
|
||||
TTgColibDrm.CreateDEK(SHA256_DIGEST_SIZE, pKek);
|
||||
|
||||
if Assigned(FOnSuccess) then
|
||||
FOnSuccess(Self, CODE_AUTH_OK); // 메인 서비스에 알림 발송
|
||||
Close; // 창 닫기
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
program login;
|
||||
|
||||
uses
|
||||
Vcl.Forms,
|
||||
authentification in 'authentification.pas' {Form1},
|
||||
Tocsg.COLib.Encrypt in 'Tocsg.COLib.Encrypt.pas';
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.MainFormOnTaskbar := True;
|
||||
Application.CreateForm(TForm1, Form1);
|
||||
Application.Run;
|
||||
end.
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -21,7 +21,7 @@ uses
|
|||
ThdUsbMon, ManagerHook, ThdSendFiles, ThdWinUpdateScan, ThdRouteMon,
|
||||
Tocsg.Process, HandleSecurity, AppCtrlDefine, Tocsg.WndUtil,
|
||||
ManagerCampaign, ManagerRule, superobject, Define, ThdReaction,
|
||||
Vcl.Graphics, DSchPiNoti, Tocsg.Win32, Tocsg.Fasoo,
|
||||
Vcl.Graphics, DSchPiNoti, Tocsg.Win32, Tocsg.Fasoo, UserAuthentification,
|
||||
ThdPrintWork, xPrintLogService, ManagerPrint, ThdScreenRecord, ProcessRecentDoc, Bs1FltCtrl, DeviceGuard.Logic;
|
||||
|
||||
{$I Define.inc}
|
||||
|
|
@ -438,6 +438,8 @@ type
|
|||
|
||||
bIgrPrtPause_: Boolean;
|
||||
|
||||
bIsManualSecurityMode_: Boolean; // 로그인 성공시 보안모드 진입 플
|
||||
|
||||
procedure Lock;
|
||||
procedure Unlock;
|
||||
procedure DevLock;
|
||||
|
|
@ -657,6 +659,9 @@ type
|
|||
|
||||
procedure ProcessEndSession;
|
||||
|
||||
// [yhkim] 로그인 시 수동모드 -> 보안모드
|
||||
procedure ChangeLoginMode(Sender: TObject; ResultCode: Integer);
|
||||
|
||||
property RcvHwnd: HWND read hRcvHwnd_;
|
||||
property DestServerUrl: String read sDestSvrUrl_;
|
||||
property Connected: Boolean read GetConnected;
|
||||
|
|
@ -1005,6 +1010,42 @@ end;
|
|||
|
||||
{ TManagerService }
|
||||
|
||||
procedure TManagerService.ChangeLoginMode(Sender: TObject; ResultCode: Integer);
|
||||
begin
|
||||
if ResultCode = CODE_AUTH_OK then
|
||||
begin
|
||||
begin
|
||||
// 서비스 가용 상태를 True로 변경 (GetModePolicy가 보안모드를 선택하도록 함)
|
||||
bIsManualSecurityMode_ := True; // 수동 인증 성공
|
||||
bIsServiceAvailable_ := True; // 서비스 가용 상태로 강제 전환
|
||||
|
||||
// GetModePolicy 로직 참조: 보안 모드 진입 시 필요한 설정 강제 적용
|
||||
try
|
||||
// 레지스트리 caller 값을 3으로 (보안모드 의미)
|
||||
SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\eCrmHomeEdition', 'caller', 3, true);
|
||||
|
||||
// 보안 모드 시작 로그 전송
|
||||
if Assigned(gMgSvc) then
|
||||
gMgSvc.SendEventLog(URI_USER_ACTION, MODE_SECURITY_START, 'Security Mode');
|
||||
|
||||
_Trace('인증 성공으로 인한 수동 모드 변경 : 수면모드 > 보안모드', 1);
|
||||
|
||||
// 정책 엔진 다시 호출 (화면 로고 업데이트 및 팝업 처리를 위해)
|
||||
GetModePolicy;
|
||||
|
||||
// 화면 로고 즉시 업데이트
|
||||
if IsScreenLogo then
|
||||
UpdateScreenLogo(true);
|
||||
|
||||
except
|
||||
on E: Exception do
|
||||
_Trace('ChangeLoginMode Error: ' + E.Message);
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Constructor TManagerService.Create(hRcvHwnd: HWND);
|
||||
|
||||
procedure InitHttp;
|
||||
|
|
@ -1085,6 +1126,18 @@ Constructor TManagerService.Create(hRcvHwnd: HWND);
|
|||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure ExecuteLogin;
|
||||
var
|
||||
LoginForm: TAuthForm;
|
||||
begin
|
||||
LoginForm := TAuthForm.Create(nil);
|
||||
|
||||
LoginForm.OnSuccess := ChangeLoginMode; // 성공했을때 호출할 함수 등록
|
||||
LoginForm.sAgentId := sAgentId_;
|
||||
LoginForm.sDestIPort := sDestIPort_;
|
||||
LoginForm.Show;
|
||||
end;
|
||||
|
||||
procedure InitAgentInfo;
|
||||
var
|
||||
sPath: String;
|
||||
|
|
@ -1151,6 +1204,9 @@ Constructor TManagerService.Create(hRcvHwnd: HWND);
|
|||
// AgentModel_.Save; 아래에서 함 22_0721 15:24:12 kku
|
||||
end;
|
||||
|
||||
//[yhkim]
|
||||
ExecuteLogin();
|
||||
|
||||
if CUSTOMER_TYPE = CUSTOMER_LOTTEMART then
|
||||
begin
|
||||
// 실행마다 NAC에서 유저 ID값 가져오기
|
||||
|
|
@ -5646,7 +5702,7 @@ begin
|
|||
SetModeName(RS_VulMode);
|
||||
end else
|
||||
// if { PrefIdlModel_.Loaded and } not VulService_.IsVpnOn then // 수면 모드는 정책 안불러와도 빈 정책을 줘야함 22_0729 07:46:15 kku
|
||||
if not bIsServiceAvailable_ then // VulService_.IsVpnOn 이걸로 체크 하면 모드별 팝업 옵션이 즉시 적용 되지 않아서 변경함 22_1222 17:08:48 kku
|
||||
if not bIsServiceAvailable_ and not bIsManualSecurityMode_ then // VulService_.IsVpnOn 이걸로 체크 하면 모드별 팝업 옵션이 즉시 적용 되지 않아서 변경함 22_1222 17:08:48 kku
|
||||
begin
|
||||
Result := PrefIdlModel_;
|
||||
SetModeKind(hmkSleep);
|
||||
|
|
|
|||
|
|
@ -512,6 +512,7 @@ procedure TRecoverService.CheckAndRecover(sResPath, sPath: String);
|
|||
sDir,
|
||||
sFName: String;
|
||||
begin
|
||||
exit;
|
||||
try
|
||||
sFName := ExtractFileName(sPath);
|
||||
Guard(zip, TAbUnzipper.Create(nil));
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue