unit DCoCryptoMain; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls; const (** * key ±æÀÌ¿¡ µû¶ó ºí·°¾Ïȣȭ ¾Ë°í¸®Áò ±¸ºÐ * 16 : 128 * 24 : 192 * 32 : 256 *) COLIB_USER_KEY_LEN = 32; type TDlgCoCryptoMain = class(TForm) mmInfo: TMemo; pnTop: TPanel; btnHashTest: TButton; btnBlcokEncTest: TButton; btnHeadEncTest: TButton; Button1: TButton; Button2: TButton; btnPbkdf2: TButton; Button3: TButton; procedure btnHashTestClick(Sender: TObject); procedure btnBlcokEncTestClick(Sender: TObject); procedure btnHeadEncTestClick(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure btnPbkdf2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } arrKey_: array [0..COLIB_USER_KEY_LEN-1] of Byte; procedure Log(sLog: String); inline; public { Public declarations } Constructor Create(aOwner: TComponent); override; end; var DlgCoCryptoMain: TDlgCoCryptoMain; implementation uses Tocsg.COLib, Tocsg.COLib.Encrypt, Tocsg.DateTime, Tocsg.Safe, System.Math, Winapi.AclAPI, Winapi.AccCtrl; {$R *.dfm} 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; // indy HMAC »ç¿ë // uses IdHMACSHA1, IdGlobal, IdSSLOpenSSL; //function PBKDF2_HMAC_SHA256(const pPass, pSalt: TBytes; Iterations, nKeyLen: Integer): TBytes; //var // i, n, nBlockCnt: Integer; // pSaltAndBlkIdx, T, U, U2: TBytes; // HMAC: TIdHMACSHA256; // pBlockIdx: TBytes; //begin // SetLength(Result, nKeyLen); // nBlockCnt := (nKeyLen + 31) div 32; // SHA256 = 32 bytes // // SetLength(pBlockIdx, 4); // SetLength(U, 32); // SetLength(U2, 32); // SetLength(T, 32); // HMAC := TIdHMACSHA256.Create; // try // HMAC.Key := TIdBytes(pPass); // for i := 1 to nBlockCnt do // begin // // BlockIndex = i (Big Endian) // 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); // // // U1 = HMAC(Password, Salt || BlockIndex) // pSaltAndBlkIdx := ConcatBytes(pSalt, pBlockIdx); // U := TBytes(HMAC.HashValue(TIdBytes(pSaltAndBlkIdx))); // // CopyMemory(T, U, Length(U)); // // for n := 2 to Iterations do // begin // U := TBytes(HMAC.HashValue(TIdBytes(U))); // XORBytes(T, U); // end; // // Move(T[0], Result[(i - 1) * 32], Min(32, nKeyLen - (i - 1) * 32)); // end; // finally // HMAC.Free; // end; //end; function PBKDF2_HMAC_SHA256(const sPass, sSalt: AnsiString; Iterations, nKeyLen: Integer): TBytes; var i, n, nBlockCnt: Integer; pSaltAndBlkIdx, pTemp, U_prev, U_current, pPass, pSalt: TBytes; pBlockIdx: TBytes; ci: TCIPHER_INFO; nOut, nResult: Integer; begin SetLength(Result, nKeyLen); ZeroMemory(Result, nKeyLen); 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, 32); SetLength(U_prev, 32); SetLength(U_current, 32); nBlockCnt := (nKeyLen + 31) div 32; // SHA256 = 32 bytes for i := 1 to nBlockCnt do begin // BlockIndex = i (Big Endian) 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); pSaltAndBlkIdx := ConcatBytes(pSalt, pBlockIdx); nOut := 0; 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; 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; XORBytes(pTemp, U_current); CopyMemory(U_prev, U_current, Length(U_current)); end; Move(pTemp[0], Result[(i - 1) * 32], Min(32, nKeyLen - (i - 1) * 32)); end; end; procedure TDlgCoCryptoMain.btnPbkdf2Click(Sender: TObject); var sOut: AnsiString; pBuf: TBytes; i: Integer; begin pBuf := PBKDF2_HMAC_SHA256('kku250507', '1234567890', 1001, 16); sOut := ''; for i := 0 to Length(pBuf) - 1 do sOut := sOut + Format('%.2x', [pBuf[i]]); Log('PBKDF2 Text : ' + sOut); end; Constructor TDlgCoCryptoMain.Create(aOwner: TComponent); var cv: TCOLIB_VERSION; begin Inherited Create(aOwner); COLibGetVersion(@cv); Log('COLib Á¤º¸ : ' + cv.version_str); mmInfo.Lines.Add(''); ZeroMemory(@arrKey_, SizeOf(arrKey_)); COLibGetKey(@arrKey_, COLIB_USER_KEY_LEN); end; procedure TDlgCoCryptoMain.Log(sLog: String); begin mmInfo.Lines.Add('[' + DateTimeToStr(Now) + '] ' + sLog); end; procedure TDlgCoCryptoMain.btnHashTestClick(Sender: TObject); var ci: TCIPHER_INFO; sIn, sOut: AnsiString; nOut, nResult: Integer; arrBuf: array [0..SHA256_DIGEST_SIZE-1] of Byte; i: Integer; begin Log('ÇØ½Ã Å×½ºÆ® (SHA256)'); ZeroMemory(@ci, SizeOf(ci)); ZeroMemory(@arrBuf, SHA256_DIGEST_SIZE); sIn := 'abcd'; sOut := ''; nOut := 0; COLibSetCipherInfo(@ci, COLIB_MODE_SHA256, BLOCK_CRYPTO_MODE_UNUSED, COLIB_PAD_TYPE_UNUSED, nil, 0, nil, 0, @sIn[1], Length(sIn), @arrBuf, @nOut); nResult := COLibEncrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibEncrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; for i := 0 to nOut - 1 do sOut := sOut + Format('%.2x', [arrBuf[i]]); Log('ÀÔ·Â : ' + sIn); Log('Ãâ·Â : ' + sOut); end; procedure TDlgCoCryptoMain.btnHeadEncTestClick(Sender: TObject); var hd: TTgCoDrmHead; nResult, nHdLen, i, nOut: Integer; ci: TCIPHER_INFO; sOut: AnsiString; arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte; pEnc, pDec: TBytes; begin Log('Çì´õ ¾Ïȣȭ Å×½ºÆ®'); nHdLen := SizeOf(hd); ZeroMemory(@hd, nHdLen); nResult := COLibGetKey(@hd.pDEK, SizeOf(hd.pDEK)); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibGetKey() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; hd.wVer := DRM_CO_VER; hd.dwCustomerCode := 13001; StrCopy(hd.sSig, PUTF8Char(SIG_CO_DRM)); StrCopy(hd.sFName, PUTF8Char(SIG_CO_DRM)); StrCopy(hd.sEmpNo, PUTF8Char(SIG_CO_DRM)); StrCopy(hd.sDeptName, PUTF8Char(SIG_CO_DRM)); StrCopy(hd.sHostName, PUTF8Char(SIG_CO_DRM)); hd.llEncDT := DelphiDtToJavaDt(Now); // sOut := ''; // for i := 0 to nHdLen - 1 do // sOut := sOut + Format('%.2x', [TBytes(@hd)[i]]); // Log('¿øº» µ¥ÀÌÅÍ (Hex) : ' + sOut); SetLength(pEnc, nHdLen + 500); ZeroMemory(pEnc, nHdLen + 500); SetLength(pDec, nHdLen + 500); ZeroMemory(pDec, nHdLen + 500); COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_PKCS, @hd.pDEK, COLIB_USER_KEY_LEN, @arrIV, 0, @hd, nHdLen, @pEnc[0], @nOut); nResult := COLibEncrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibEncrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; sOut := ''; for i := 0 to nOut - 1 do sOut := sOut + Format('%.2x', [pEnc[i]]); Log('¾Ïȣȭ µ¥ÀÌÅÍ (Hex) : ' + sOut); COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_PKCS, @hd.pDEK, COLIB_USER_KEY_LEN, @arrIV, 0, @pEnc[0], nOut, @pDec[0], @nOut); nResult := COLibDecrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibDecrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; // sOut := ''; // for i := 0 to nOut - 1 do // sOut := sOut + Format('%.2x', [pDec[i]]); // Log('º¹È£È­ µ¥ÀÌÅÍ (Hex) : ' + sOut); Log('º¹È£È­ µ¥ÀÌÅÍ ¹®ÀÚ¿­ Ãâ·Â : ' + PTgCoDrmHead(@pDec[0]).sSig); end; procedure TDlgCoCryptoMain.Button1Click(Sender: TObject); const BUF_LEN_64K = 1024 * 64; var sPath: String; fsSrc, fsDst: TFileStream; arrBuf, arrEnc: array [0..BUF_LEN_64K-1] of Byte; dwRead: DWORD; nOut, nResult: Integer; pt: TCOLIB_PAD_TYPE; ci: TCIPHER_INFO; arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte; begin sPath := 'C:\Users\kku\Desktop\TEST\123.mp4'; if not FileExists(sPath) then exit; ZeroMemory(@ci, SizeOf(ci)); ZeroMemory(@arrIV, SizeOf(arrIV)); Guard(fsSrc, TFileStream.Create(sPath, fmOpenRead)); Guard(fsDst, TFileStream.Create(sPath + '.1', fmCreate)); while fsSrc.Position < fsSrc.Size do begin dwRead := fsSrc.Read(arrBuf, BUF_LEN_64K); if (dwRead mod COLIB_BLOCK_LEN) = 0 then pt := COLIB_PAD_TYPE_NO else pt := COLIB_PAD_TYPE_PKCS; COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, pt, @arrKey_, COLIB_USER_KEY_LEN, @arrIV, 0, @arrBuf, dwRead, @arrEnc, @nOut); nResult := COLibEncrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibEncrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; fsDst.Write(arrEnc, nOut); end; end; procedure TDlgCoCryptoMain.Button2Click(Sender: TObject); const BUF_LEN_64K = 1024 * 64; var sPath: String; fsSrc, fsDst: TFileStream; arrBuf, arrEnc: array [0..BUF_LEN_64K-1] of Byte; dwRead: DWORD; nOut, nResult: Integer; pt: TCOLIB_PAD_TYPE; ci: TCIPHER_INFO; arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte; begin sPath := 'C:\Users\kku\Desktop\TEST\123.mp4.1'; if not FileExists(sPath) then exit; ZeroMemory(@ci, SizeOf(ci)); ZeroMemory(@arrIV, SizeOf(arrIV)); Guard(fsSrc, TFileStream.Create(sPath, fmOpenRead)); Guard(fsDst, TFileStream.Create(sPath + '.mp4', fmCreate)); 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; COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, pt, @arrKey_, COLIB_USER_KEY_LEN, @arrIV, 0, @arrBuf, dwRead, @arrEnc, @nOut); nResult := COLibDecrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibDecrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; fsDst.Write(arrEnc, nOut); end; end; function ProtectProcessHandle: Boolean; var hProcess: THandle; pSD: PSECURITY_DESCRIPTOR; pA: PACL; ea: EXPLICIT_ACCESS; dwRes: DWORD; begin Result := false; hProcess := GetCurrentProcess; // ¸ðµç »ç¿ëÀÚ¿¡ ´ëÇÑ Á¢±Ù ±ÇÇÑ Á¦°Å¿ë ACE ¼³Á¤ ZeroMemory(@ea, SizeOf(EXPLICIT_ACCESS)); ea.grfAccessPermissions := PROCESS_ALL_ACCESS; ea.grfAccessMode := DENY_ACCESS; ea.grfInheritance := NO_INHERITANCE; ea.Trustee.TrusteeForm := TRUSTEE_IS_NAME; ea.Trustee.TrusteeType := TRUSTEE_IS_WELL_KNOWN_GROUP; ea.Trustee.ptstrName := 'Everyone'; // DACL »ý¼º dwRes := SetEntriesInAcl(1, @ea, nil, pA); if dwRes <> ERROR_SUCCESS then begin Writeln('SetEntriesInAcl failed: ', dwRes); Exit; end; // º¸¾È Á¤º¸ ¼³Á¤ dwRes := SetSecurityInfo(hProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, pA, nil); Result := dwRes = ERROR_SUCCESS; // if dwRes <> ERROR_SUCCESS then // Writeln('SetSecurityInfo failed: ', dwRes) // else // Writeln('Process handle protection applied successfully.'); // Á¤¸® if pA <> nil then LocalFree(HLOCAL(pA)); end; procedure ProtectProcessFromTerminate; const ACL_REVISION = 2; var hProcess: THandle; res: DWORD; acl: TACL; begin ZeroMemory(@acl, SizeOf(acl)); if InitializeAcl(acl, SizeOf(acl), ACL_REVISION) then begin hProcess := GetCurrentProcess; // DACLÀ» ºñ¿ö¼­ (NULLÀÌ ¾Æ´Ô) ´Ù¸¥ »ç¿ëÀÚ Á¢±Ù Â÷´Ü res := SetSecurityInfo( hProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, @acl, nil ); if res <> ERROR_SUCCESS then RaiseLastOSError(res); end; end; procedure RemoveDebugPrivilege; var hToken: THandle; tkp: TOKEN_PRIVILEGES; dwLen: DWORD; begin OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken); LookupPrivilegeValue(nil, 'SeDebugPrivilege', tkp.Privileges[0].Luid); tkp.PrivilegeCount := 1; tkp.Privileges[0].Attributes := SE_PRIVILEGE_REMOVED; AdjustTokenPrivileges(hToken, FALSE, tkp, 0, nil, dwLen); CloseHandle(hToken); end; function SetProcessAsProtected: Boolean; const ProcessProtectionLevelInfo = 34; PROTECTION_LEVEL_WINTCB_LIGHT = 2; PROTECTION_LEVEL_WINTCB = 1; PROTECTION_LEVEL_ANTIMALWARE = 3; type PROCESS_PROTECTION_LEVEL_INFORMATION = record ProtectionLevel: DWORD; end; var hProcess: THandle; ppli: PROCESS_PROTECTION_LEVEL_INFORMATION; begin Result := False; hProcess := GetCurrentProcess; // Protected Process Light (PPL)·Î ¼³Á¤ ZeroMemory(@ppli, SizeOf(ppli)); ppli.ProtectionLevel := PROTECTION_LEVEL_WINTCB_LIGHT; if SetProcessInformation(hProcess, TProcessInformationClass(ProcessProtectionLevelInfo), @ppli, SizeOf(ppli)) then Result := True else OutputDebugString(PChar('º¸È£ ¼³Á¤ ½ÇÆÐ: ' + SysErrorMessage(GetLastError))); CloseHandle(hProcess); end; procedure TDlgCoCryptoMain.Button3Click(Sender: TObject); begin ProtectProcessHandle; // ProtectProcessFromTerminate; // SetProcessShutdownParameters($3FF, SHUTDOWN_NORETRY); // RemoveDebugPrivilege; // if SetProcessAsProtected then // ShowMessage('ÇÁ·Î¼¼½º°¡ Protected Process Light·Î º¸È£µÇ¾ú½À´Ï´Ù!') // else // ShowMessage('º¸È£ ¼³Á¤ ½ÇÆÐ. °ü¸®ÀÚ ±ÇÇÑÀ¸·Î ½ÇÇàÇϼ¼¿ä.'); end; procedure TDlgCoCryptoMain.btnBlcokEncTestClick(Sender: TObject); var sIn, sOut: AnsiString; nResult, nOut, i: Integer; ci: TCIPHER_INFO; pBuf: TBytes; arrIV: array [0..COLIB_BLOCK_LEN-1] of Byte; {arrKey, }arrEnc, arrDec: array [0..COLIB_USER_KEY_LEN-1] of Byte; begin Log('ºí·Ï ¾Ïȣȭ (ARIA)'); sIn := 'abcdefg97'; // sIn := '123456789012345'; Log('ÀÔ·Â : ' + sIn); ZeroMemory(@ci, SizeOf(ci)); // ZeroMemory(@arrKey, SizeOf(arrKey)); ZeroMemory(@arrIV, SizeOf(arrIV)); ZeroMemory(@arrEnc, SizeOf(arrEnc)); ZeroMemory(@arrDec, SizeOf(arrDec)); // nResult := COLibGetKey(@arrKey, COLIB_USER_KEY_LEN); // if nResult <> COLIB_SUCCESS then // begin // Log('Fail .. COLibGetKey() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); // exit; // end; nResult := COLibDrbg(@arrIV, SizeOf(arrIV), nil, 0, nil, 0, 0); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibDrbg() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_PKCS, @arrKey_, COLIB_USER_KEY_LEN, @arrIV, SizeOf(arrIV), @sIn[1], Length(sIn), @arrEnc, @nOut); nResult := COLibEncrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibEncrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; sOut := ''; for i := 0 to nOut - 1 do sOut := sOut + Format('%.2x', [arrEnc[i]]); Log('¾Ïȣȭ µ¥ÀÌÅÍ (Hex) : ' + sOut); COLibSetCipherInfo(@ci, COLIB_MODE_ARIA, BLOCK_CRYPTO_MODE_CBC, COLIB_PAD_TYPE_PKCS, @arrKey_, COLIB_USER_KEY_LEN, @arrIV, SizeOf(arrIV), @arrEnc, nOut, @arrDec, @nOut); nResult := COLibDecrypt(@ci); if nResult <> COLIB_SUCCESS then begin Log('Fail .. COLibDecrypt() .. Error=' + IntToStr(nResult) + ', ' + COLibGetErrorStr(nResult)); exit; end; sOut := ''; for i := 0 to nOut - 1 do sOut := sOut + Format('%.2x', [arrDec[i]]); Log('º¹È£È­ µ¥ÀÌÅÍ (Hex) : ' + sOut); Log('º¹È£È­ µ¥ÀÌÅÍ ¹®ÀÚ¿­ Ãâ·Â : ' + PAnsiChar(@arrDec)); // COLibZeroCipherInfo(@ci); end; end.