delphi数字签名验证及能够获取数字签名文件信息(利用wintrust.dll的导出函数,翻译一下)

时间:2022-10-14 00:16:47
unit TrustCheck;

interface

uses
  Windows,SysUtils,jwaWinTrust,JwaWinCrypt;


function CheckFileTrust(const FileName: WideString; var Signner: WideString): Boolean;

implementation



const
  WINTRUST_ACTION_GENERIC_VERIFY_V2: TGUID = '{00AAC56B-CD44-11d0-8CC2-00C04FC295EE}';

  function CryptCATAdminAcquireContext(var HCatAdmin: THandle; pgSubsystem: PGUID; dwFlags: DWORD): BOOL; stdcall; external 'wintrust.dll' ;
  function CryptCATAdminReleaseContext(hAdmin: THANDLE; dwFlags: DWORD): BOOL; stdcall; external 'wintrust.dll' ;
  function CryptCATAdminCalcHashFromFileHandle(hFile: THANDLE; var dwSize: DWORD; buf: PByte; dwFlags: DWORD): BOOL; stdcall; external 'wintrust.dll' ;
  function CryptCATAdminEnumCatalogFromHash(hAdmin: THANDLE; pbHash: PByte; pHashSize: DWORD; dwFlags: DWORD; phPrevCatInfo: PHandle): THANDLE; stdcall;external 'wintrust.dll' ;
  function CryptCATCatalogInfoFromContext(hCatInfo: THANDLE; psCatInfo: PWintrustCatalogInfo; dwFlags: DWORD): BOOL; stdcall; external 'wintrust.dll' ;
  function CryptCATAdminReleaseCatalogContext(hAdmin: THANDLE; hCatInfo: THANDLE; dwFlags: DWORD): BOOL; stdcall; external 'wintrust.dll' ;
  function WinVerifyTrust(hwnd: THANDLE; pgActionID: PGUID; pWintrustData: PWINTRUST_DATA): Longint; stdcall; external 'wintrust.dll' ;


function bf2s(bf: PByte; len: Integer): WideString;
begin
  Result := '';
  while len > 0 do
  begin
    Result := Result + IntToHex(bf^,2);
    Inc(bf);
    Dec(len);
  end;
end;

function GetSignner(hWVTStateData: THANDLE): WideString;
var
  provider: PCRYPT_PROVIDER_DATA;
  signner:  PCRYPT_PROVIDER_SGNR;
  cert:     PCRYPT_PROVIDER_CERT;
  S:        string;
  i:        Integer;
begin
  provider := WTHelperProvDataFromStateData(hWVTStateData);
  if provider = nil then
    Exit;
  signner := WTHelperGetProvSignerFromChain(provider,0,False,0);
  if signner = nil then
    Exit;
  cert := WTHelperGetProvCertFromChain(signner, 0);
  if cert = nil then
    Exit;
  i := CertGetNameString(cert.pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, nil, 0);
  SetLength(S,i);
  CertGetNameString(cert.pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, nil, @s[1], Length(s));
  Result := S;
end;

function CheckFileTrust(const FileName: WideString; var Signner: WideString): Boolean;
var
  buf: array[0..255]of Byte;
  cb: DWORD;
  hAdmin: THandle;
  hCtx:   THandle;
  hFile:  THandle;
  I,Ret: Integer;
  S: WideString;
  WTrustData: WINTRUST_DATA;
  WTDFileInfo: TWintrustFileInfo;
  CatalogInfo: TWintrustCatalogInfo;
  WTDCatalogInfo: WINTRUST_CATALOG_INFO;
begin
  Result := False;
  Signner := '';
  if not FileExists(FileName) then
    Exit;
  hAdmin := 0;
  hCtx   := 0;
  hFile  := INVALID_HANDLE_VALUE;
  try
    if not CryptCATAdminAcquireContext(hAdmin,nil,0) then
      Exit;
    hFile := CreateFileW(PWideChar(FileName),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    if hFile = INVALID_HANDLE_VALUE then
    begin
      I := GetLastError;
      sleep(I * 0);
      Exit;
    end;
    cb := SizeOf(buf);
    if not CryptCATAdminCalcHashFromFileHandle(hFile,cb,@buf[0],0) then
      Exit;
    S := bf2s(@buf[0],cb);
    hCtx := CryptCATAdminEnumCatalogFromHash(hAdmin,@buf[0],cb,0,nil);
    FillChar(WTrustData,SizeOf(WTrustData),0);

    WTrustData.dwUIChoice          := WTD_UI_NONE;
    WTrustData.fdwRevocationChecks := WTD_REVOKE_NONE;
    WTrustData.dwStateAction       := WTD_STATEACTION_VERIFY;
    WTrustData.dwProvFlags         := WTD_REVOCATION_CHECK_NONE;
    if hCtx = 0 then
    begin
      FillChar(WTDFileInfo,SizeOf(WTDFileInfo),0);
      WTDFileInfo.cbStruct := SizeOf(WTDFileInfo);
      WTDFileInfo.pcwszFilePath := PWideChar(FileName);
      WTrustData.cbStruct := SizeOf(WTrustData);
      WTrustData.dwUnionChoice := WTD_CHOICE_FILE;
      WTrustData.InfoUnion.pFile := @WTDFileInfo;
    end
    else
    begin
      CryptCATCatalogInfoFromContext(hCtx, @CatalogInfo, 0);
      FillChar(WTDCatalogInfo,SizeOf(WTDCatalogInfo),0);
      WTDCatalogInfo.cbStruct := SizeOf(WTDCatalogInfo);
      WTDCatalogInfo.pcwszCatalogFilePath := CatalogInfo.pcwszCatalogFilePath;
      WTDCatalogInfo.pcwszMemberFilePath := PWideChar(Filename);
      WTDCatalogInfo.pcwszMemberTag := PWideChar(S);
      WTrustData.cbStruct := SizeOf(WTrustData);
      WTrustData.dwUnionChoice := WTD_CHOICE_CATALOG;
      WTrustData.InfoUnion.pCatalog := @WTDCatalogInfo;
    end;
    Ret := WinVerifyTrust(INVALID_HANDLE_VALUE,@WINTRUST_ACTION_GENERIC_VERIFY_V2,@WTrustData);
    Result := Ret = 0;
    if Result and (WTrustData.hWVTStateData > 0) then
      Signner := GetSignner(WTrustData.hWVTStateData);
    WTrustData.dwStateAction := WTD_STATEACTION_CLOSE;
    WinVerifyTrust(INVALID_HANDLE_VALUE,@WINTRUST_ACTION_GENERIC_VERIFY_V2,@WTrustData);
  finally
    if hCtx > 0 then
      CryptCATAdminReleaseCatalogContext(hAdmin,hCtx, 0);
    if hAdmin <> 0 then
      CryptCATAdminReleaseContext(hAdmin,0);
    if hFile <> INVALID_HANDLE_VALUE then
      CloseHandle(hFile);
  end;
end;

end.