{*******************************************************} { } { Tocsg.Cert } { } { Copyright (C) 2025 kku } { } {*******************************************************} unit Tocsg.Cert; interface uses Winapi.Windows; //const // CERT_QUERY_OBJECT_FILE = $00000001; // CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = $00000020; // CERT_QUERY_FORMAT_FLAG_BINARY = $00000002; // CMSG_SIGNER_INFO_PARAM = 6; // CERT_NAME_SIMPLE_DISPLAY_TYPE = 4; // CERT_X500_NAME_STR = 3; // CERT_FIND_SUBJECT_CERT = $0000000B; // // X509_ASN_ENCODING = $00000001; // X.509 인증서 인코딩 // PKCS_7_ASN_ENCODING = $00010000; // PKCS#7 서명 인코딩 // ENCODING_TYPE = (X509_ASN_ENCODING or PKCS_7_ASN_ENCODING); // //type // HCERTSTORE = Pointer; // HCRYPTMSG = Pointer; // PCCERT_CONTEXT = ^CERT_CONTEXT; // //function CryptQueryObject(dwObjectType: DWORD; pvObject: PChar; // dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags: DWORD; // dwFlags: DWORD; var pdwMsgAndCertEncodingType, pdwContentType, // pdwFormatType: DWORD; var phCertStore: HCERTSTORE; // var phMsg: HCRYPTMSG; ppvContext: Pointer): BOOL; stdcall; // external 'Crypt32.dll'; // //function CryptMsgGetParam(hCryptMsg: HCRYPTMSG; dwParamType, dwIndex: DWORD; // pvData: Pointer; var pcbData: DWORD): BOOL; stdcall; // external 'Crypt32.dll'; // //function CertNameToStr(dwCertEncodingType: DWORD; pName: PCERT_NAME_BLOB; // dwStrType: DWORD; psz: PChar; csz: DWORD): DWORD; stdcall; // external 'Crypt32.dll' name 'CertNameToStrW'; // //function CertFindCertificateInStore(hCertStore: HCERTSTORE; // dwCertEncodingType: DWORD; dwFindFlags: DWORD; // dwFindType: DWORD; pvFindPara: Pointer; // pPrevCertContext: PCCERT_CONTEXT): PCCERT_CONTEXT; stdcall; // external 'Crypt32.dll'; // //function CertFreeCertificateContext(pCertContext: PCCERT_CONTEXT): BOOL; stdcall; // external 'Crypt32.dll'; // //function CertCloseStore(hCertStore: HCERTSTORE; dwFlags: DWORD): BOOL; stdcall; // external 'Crypt32.dll'; // //function CryptMsgClose(hCryptMsg: HCRYPTMSG): BOOL; stdcall; // external 'Crypt32.dll'; function IsFileSigned(const FileName: string): Boolean; implementation function IsFileSigned(const FileName: string): Boolean; var WinTrustData: WINTRUST_DATA; WinTrustFileInfo: WINTRUST_FILE_INFO; GuidAction: TGUID; begin Result := False; // GUID 설정 (WINTRUST_ACTION_GENERIC_VERIFY_V2) GuidAction := WINTRUST_ACTION_GENERIC_VERIFY_V2; // WINTRUST_FILE_INFO 초기화 ZeroMemory(@WinTrustFileInfo, SizeOf(WinTrustFileInfo)); WinTrustFileInfo.cbStruct := SizeOf(WinTrustFileInfo); WinTrustFileInfo.pcwszFilePath := PWideChar(WideString(FileName)); WinTrustFileInfo.hFile := 0; WinTrustFileInfo.pgKnownSubject := nil; // WINTRUST_DATA 초기화 ZeroMemory(@WinTrustData, SizeOf(WinTrustData)); WinTrustData.cbStruct := SizeOf(WinTrustData); WinTrustData.dwUIChoice := WTD_UI_NONE; // UI 없음 WinTrustData.fdwRevocationChecks := WTD_REVOKE_NONE; // 인증서 폐기 목록(CRL) 체크 안 함 WinTrustData.dwUnionChoice := WTD_CHOICE_FILE; // 파일 검사 WinTrustData.pFile := @WinTrustFileInfo; // 검사할 파일 정보 WinTrustData.dwStateAction := 0; WinTrustData.hWVTStateData := 0; WinTrustData.pwszURLReference := nil; WinTrustData.dwProvFlags := WTD_SAFER_FLAG; // 서명 확인 Result := WinVerifyTrust(0, GuidAction, @WinTrustData) = ERROR_SUCCESS; end; //function GetCertificateInfo(const FileName: string): string; //var // hFile: THandle; // hFileMapping: THandle; // pbFile: Pointer; // hStore: HCERTSTORE; // hMsg: HCRYPTMSG; // CertContext: PCCERT_CONTEXT; // Encoding, ContentType, FormatType: DWORD; // SignerInfo: PCMSG_SIGNER_INFO; // dwSignerInfo: DWORD; // IssuerName, SubjectName: array[0..1023] of Char; //begin // Result := '서명 정보 없음'; // // // 파일 열기 // if not CryptQueryObject(CERT_QUERY_OBJECT_FILE, PChar(FileName), // CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, // CERT_QUERY_FORMAT_FLAG_BINARY, 0, Encoding, // ContentType, FormatType, hStore, hMsg, nil) then // begin // Exit; // end; // // // 서명자 정보 크기 확인 // if not CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, nil, dwSignerInfo) then // begin // Exit; // end; // // // 서명자 정보 가져오기 // GetMem(SignerInfo, dwSignerInfo); // try // if not CryptMsgGetParam(hMsg, CMSG_SIGNER_INFO_PARAM, 0, SignerInfo, dwSignerInfo) then // begin // Exit; // end; // // // 인증서 찾기 // CertContext := CertFindCertificateInStore(hStore, ENCODING_TYPE, // 0, CERT_FIND_SUBJECT_CERT, @SignerInfo^.Issuer, nil); // // if Assigned(CertContext) then // begin // // 발급자 정보 // CertNameToStr(CERT_X500_NAME_STR, @CertContext^.pCertInfo^.Issuer, // CERT_NAME_SIMPLE_DISPLAY_TYPE, IssuerName, SizeOf(IssuerName)); // // // 서명자 정보 // CertNameToStr(CERT_X500_NAME_STR, @CertContext^.pCertInfo^.Subject, // CERT_NAME_SIMPLE_DISPLAY_TYPE, SubjectName, SizeOf(SubjectName)); // // Result := Format('발급자: %s' + sLineBreak + '서명자: %s', [IssuerName, SubjectName]); // end; // finally // FreeMem(SignerInfo); // if Assigned(CertContext) then // CertFreeCertificateContext(CertContext); // if hStore <> nil then // CertCloseStore(hStore, 0); // if hMsg <> nil then // CryptMsgClose(hMsg); // end; //end; end.