2016-04-29 13 views
6

実行ファイルのコード署名に関する情報を取得するために、次のコード(KB323809 articleから取得)を使用しています。これは、単一のデジタル署名でうまく動作します。実行可能ファイルの複数/二重コード署名から情報を取得する方法

しかし、複数のコード署名の情報を取得するにはどうすればよいですか?

この場合、以下のMicrosoftコードは、単に最初の署名の情報のみを取得します。

私の考えは、(下記のコードで)署名の数を取得するCMSG_SIGNER_COUNT_PARAMCryptMsgGetParamを呼び出し、次いでCMSG_SIGNER_INFO_PARAMCryptMsgGetParamに後続の呼び出しに各シグネチャインデックスを通過することであった。しかし、このアプローチは、常に場合でも、1人の署名を返すI代わりに、追加のPKCS 7、署名者の主要署名者(インデックス0)のUnauthenticatedAttributes、で

enter image description here

#include <windows.h> 
#include <wincrypt.h> 
#include <wintrust.h> 
#include <stdio.h> 
#include <tchar.h> 

#pragma comment(lib, "crypt32.lib") 

#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING) 

typedef struct { 
    LPWSTR lpszProgramName; 
    LPWSTR lpszPublisherLink; 
    LPWSTR lpszMoreInfoLink; 
} SPROG_PUBLISHERINFO, *PSPROG_PUBLISHERINFO; 

BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo, 
          PSPROG_PUBLISHERINFO Info); 
BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st); 
BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext); 
BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, 
          PCMSG_SIGNER_INFO *pCounterSignerInfo); 

int _tmain(int argc, TCHAR *argv[]) 
{ 
    WCHAR szFileName[MAX_PATH]; 
    HCERTSTORE hStore = NULL; 
    HCRYPTMSG hMsg = NULL; 
    PCCERT_CONTEXT pCertContext = NULL; 
    BOOL fResult; 
    DWORD dwEncoding, dwContentType, dwFormatType; 
    PCMSG_SIGNER_INFO pSignerInfo = NULL; 
    PCMSG_SIGNER_INFO pCounterSignerInfo = NULL; 
    DWORD dwSignerInfo; 
    CERT_INFO CertInfo;  
    SPROG_PUBLISHERINFO ProgPubInfo; 
    SYSTEMTIME st; 

    ZeroMemory(&ProgPubInfo, sizeof(ProgPubInfo)); 
    __try 
    { 
     if (argc != 2) 
     { 
      _tprintf(_T("Usage: SignedFileInfo <filename>\n")); 
      return 0; 
     } 

#ifdef UNICODE 
     lstrcpynW(szFileName, argv[1], MAX_PATH); 
#else 
     if (mbstowcs(szFileName, argv[1], MAX_PATH) == -1) 
     { 
      printf("Unable to convert to unicode.\n"); 
      __leave; 
     } 
#endif 

     // Get message handle and store handle from the signed file. 
     fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE, 
            szFileName, 
            CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, 
            CERT_QUERY_FORMAT_FLAG_BINARY, 
            0, 
            &dwEncoding, 
            &dwContentType, 
            &dwFormatType, 
            &hStore, 
            &hMsg, 
            NULL); 
     if (!fResult) 
     { 
      _tprintf(_T("CryptQueryObject failed with %x\n"), GetLastError()); 
      __leave; 
     } 

     // Get signer information size. 
     fResult = CryptMsgGetParam(hMsg, 
            CMSG_SIGNER_INFO_PARAM, 
            0, 
            NULL, 
            &dwSignerInfo); 
     if (!fResult) 
     { 
      _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError()); 
      __leave; 
     } 

     // Allocate memory for signer information. 
     pSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSignerInfo); 
     if (!pSignerInfo) 
     { 
      _tprintf(_T("Unable to allocate memory for Signer Info.\n")); 
      __leave; 
     } 

     // Get Signer Information. 
     fResult = CryptMsgGetParam(hMsg, 
            CMSG_SIGNER_INFO_PARAM, 
            0, 
            (PVOID)pSignerInfo, 
            &dwSignerInfo); 
     if (!fResult) 
     { 
      _tprintf(_T("CryptMsgGetParam failed with %x\n"), GetLastError()); 
      __leave; 
     } 

     // Get program name and publisher information from 
     // signer info structure. 
     if (GetProgAndPublisherInfo(pSignerInfo, &ProgPubInfo)) 
     { 
      if (ProgPubInfo.lpszProgramName != NULL) 
      { 
       wprintf(L"Program Name : %s\n", 
        ProgPubInfo.lpszProgramName); 
      } 

      if (ProgPubInfo.lpszPublisherLink != NULL) 
      { 
       wprintf(L"Publisher Link : %s\n", 
        ProgPubInfo.lpszPublisherLink); 
      } 

      if (ProgPubInfo.lpszMoreInfoLink != NULL) 
      { 
       wprintf(L"MoreInfo Link : %s\n", 
        ProgPubInfo.lpszMoreInfoLink); 
      } 
     } 

     _tprintf(_T("\n")); 

     // Search for the signer certificate in the temporary 
     // certificate store. 
     CertInfo.Issuer = pSignerInfo->Issuer; 
     CertInfo.SerialNumber = pSignerInfo->SerialNumber; 

     pCertContext = CertFindCertificateInStore(hStore, 
                ENCODING, 
                0, 
                CERT_FIND_SUBJECT_CERT, 
                (PVOID)&CertInfo, 
                NULL); 
     if (!pCertContext) 
     { 
      _tprintf(_T("CertFindCertificateInStore failed with %x\n"), 
       GetLastError()); 
      __leave; 
     } 

     // Print Signer certificate information. 
     _tprintf(_T("Signer Certificate:\n\n"));   
     PrintCertificateInfo(pCertContext); 
     _tprintf(_T("\n")); 

     // Get the timestamp certificate signerinfo structure. 
     if (GetTimeStampSignerInfo(pSignerInfo, &pCounterSignerInfo)) 
     { 
      // Search for Timestamp certificate in the temporary 
      // certificate store. 
      CertInfo.Issuer = pCounterSignerInfo->Issuer; 
      CertInfo.SerialNumber = pCounterSignerInfo->SerialNumber; 

      pCertContext = CertFindCertificateInStore(hStore, 
               ENCODING, 
               0, 
               CERT_FIND_SUBJECT_CERT, 
               (PVOID)&CertInfo, 
               NULL); 
      if (!pCertContext) 
      { 
       _tprintf(_T("CertFindCertificateInStore failed with %x\n"), 
        GetLastError()); 
       __leave; 
      } 

      // Print timestamp certificate information. 
      _tprintf(_T("TimeStamp Certificate:\n\n")); 
      PrintCertificateInfo(pCertContext); 
      _tprintf(_T("\n")); 

      // Find Date of timestamp. 
      if (GetDateOfTimeStamp(pCounterSignerInfo, &st)) 
      { 
       _tprintf(_T("Date of TimeStamp : %02d/%02d/%04d %02d:%02d\n"), 
              st.wMonth, 
              st.wDay, 
              st.wYear, 
              st.wHour, 
              st.wMinute); 
      } 
      _tprintf(_T("\n")); 
     } 
    } 
    __finally 
    {    
     // Clean up. 
     if (ProgPubInfo.lpszProgramName != NULL) 
      LocalFree(ProgPubInfo.lpszProgramName); 
     if (ProgPubInfo.lpszPublisherLink != NULL) 
      LocalFree(ProgPubInfo.lpszPublisherLink); 
     if (ProgPubInfo.lpszMoreInfoLink != NULL) 
      LocalFree(ProgPubInfo.lpszMoreInfoLink); 

     if (pSignerInfo != NULL) LocalFree(pSignerInfo); 
     if (pCounterSignerInfo != NULL) LocalFree(pCounterSignerInfo); 
     if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); 
     if (hStore != NULL) CertCloseStore(hStore, 0); 
     if (hMsg != NULL) CryptMsgClose(hMsg); 
    } 
    return 0; 
} 

BOOL PrintCertificateInfo(PCCERT_CONTEXT pCertContext) 
{ 
    BOOL fReturn = FALSE; 
    LPTSTR szName = NULL; 
    DWORD dwData; 

    __try 
    { 
     // Print Serial Number. 
     _tprintf(_T("Serial Number: ")); 
     dwData = pCertContext->pCertInfo->SerialNumber.cbData; 
     for (DWORD n = 0; n < dwData; n++) 
     { 
      _tprintf(_T("%02x "), 
       pCertContext->pCertInfo->SerialNumber.pbData[dwData - (n + 1)]); 
     } 
     _tprintf(_T("\n")); 

     // Get Issuer name size. 
     if (!(dwData = CertGetNameString(pCertContext, 
             CERT_NAME_SIMPLE_DISPLAY_TYPE, 
             CERT_NAME_ISSUER_FLAG, 
             NULL, 
             NULL, 
             0))) 
     { 
      _tprintf(_T("CertGetNameString failed.\n")); 
      __leave; 
     } 

     // Allocate memory for Issuer name. 
     szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR)); 
     if (!szName) 
     { 
      _tprintf(_T("Unable to allocate memory for issuer name.\n")); 
      __leave; 
     } 

     // Get Issuer name. 
     if (!(CertGetNameString(pCertContext, 
           CERT_NAME_SIMPLE_DISPLAY_TYPE, 
           CERT_NAME_ISSUER_FLAG, 
           NULL, 
           szName, 
           dwData))) 
     { 
      _tprintf(_T("CertGetNameString failed.\n")); 
      __leave; 
     } 

     // print Issuer name. 
     _tprintf(_T("Issuer Name: %s\n"), szName); 
     LocalFree(szName); 
     szName = NULL; 

     // Get Subject name size. 
     if (!(dwData = CertGetNameString(pCertContext, 
             CERT_NAME_SIMPLE_DISPLAY_TYPE, 
             0, 
             NULL, 
             NULL, 
             0))) 
     { 
      _tprintf(_T("CertGetNameString failed.\n")); 
      __leave; 
     } 

     // Allocate memory for subject name. 
     szName = (LPTSTR)LocalAlloc(LPTR, dwData * sizeof(TCHAR)); 
     if (!szName) 
     { 
      _tprintf(_T("Unable to allocate memory for subject name.\n")); 
      __leave; 
     } 

     // Get subject name. 
     if (!(CertGetNameString(pCertContext, 
           CERT_NAME_SIMPLE_DISPLAY_TYPE, 
           0, 
           NULL, 
           szName, 
           dwData))) 
     { 
      _tprintf(_T("CertGetNameString failed.\n")); 
      __leave; 
     } 

     // Print Subject Name. 
     _tprintf(_T("Subject Name: %s\n"), szName); 

     fReturn = TRUE; 
    } 
    __finally 
    { 
     if (szName != NULL) LocalFree(szName); 
    } 

    return fReturn; 
} 

LPWSTR AllocateAndCopyWideString(LPCWSTR inputString) 
{ 
    LPWSTR outputString = NULL; 

    outputString = (LPWSTR)LocalAlloc(LPTR, 
     (wcslen(inputString) + 1) * sizeof(WCHAR)); 
    if (outputString != NULL) 
    { 
     lstrcpyW(outputString, inputString); 
    } 
    return outputString; 
} 

BOOL GetProgAndPublisherInfo(PCMSG_SIGNER_INFO pSignerInfo, 
          PSPROG_PUBLISHERINFO Info) 
{ 
    BOOL fReturn = FALSE; 
    PSPC_SP_OPUS_INFO OpusInfo = NULL; 
    DWORD dwData; 
    BOOL fResult; 

    __try 
    { 
     // Loop through authenticated attributes and find 
     // SPC_SP_OPUS_INFO_OBJID OID. 
     for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) 
     {   
      if (lstrcmpA(SPC_SP_OPUS_INFO_OBJID, 
         pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0) 
      { 
       // Get Size of SPC_SP_OPUS_INFO structure. 
       fResult = CryptDecodeObject(ENCODING, 
          SPC_SP_OPUS_INFO_OBJID, 
          pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData, 
          pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData, 
          0, 
          NULL, 
          &dwData); 
       if (!fResult) 
       { 
        _tprintf(_T("CryptDecodeObject failed with %x\n"), 
         GetLastError()); 
        __leave; 
       } 

       // Allocate memory for SPC_SP_OPUS_INFO structure. 
       OpusInfo = (PSPC_SP_OPUS_INFO)LocalAlloc(LPTR, dwData); 
       if (!OpusInfo) 
       { 
        _tprintf(_T("Unable to allocate memory for Publisher Info.\n")); 
        __leave; 
       } 

       // Decode and get SPC_SP_OPUS_INFO structure. 
       fResult = CryptDecodeObject(ENCODING, 
          SPC_SP_OPUS_INFO_OBJID, 
          pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData, 
          pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData, 
          0, 
          OpusInfo, 
          &dwData); 
       if (!fResult) 
       { 
        _tprintf(_T("CryptDecodeObject failed with %x\n"), 
         GetLastError()); 
        __leave; 
       } 

       // Fill in Program Name if present. 
       if (OpusInfo->pwszProgramName) 
       { 
        Info->lpszProgramName = 
         AllocateAndCopyWideString(OpusInfo->pwszProgramName); 
       } 
       else 
        Info->lpszProgramName = NULL; 

       // Fill in Publisher Information if present. 
       if (OpusInfo->pPublisherInfo) 
       { 

        switch (OpusInfo->pPublisherInfo->dwLinkChoice) 
        { 
         case SPC_URL_LINK_CHOICE: 
          Info->lpszPublisherLink = 
           AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszUrl); 
          break; 

         case SPC_FILE_LINK_CHOICE: 
          Info->lpszPublisherLink = 
           AllocateAndCopyWideString(OpusInfo->pPublisherInfo->pwszFile); 
          break; 

         default: 
          Info->lpszPublisherLink = NULL; 
          break; 
        } 
       } 
       else 
       { 
        Info->lpszPublisherLink = NULL; 
       } 

       // Fill in More Info if present. 
       if (OpusInfo->pMoreInfo) 
       { 
        switch (OpusInfo->pMoreInfo->dwLinkChoice) 
        { 
         case SPC_URL_LINK_CHOICE: 
          Info->lpszMoreInfoLink = 
           AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszUrl); 
          break; 

         case SPC_FILE_LINK_CHOICE: 
          Info->lpszMoreInfoLink = 
           AllocateAndCopyWideString(OpusInfo->pMoreInfo->pwszFile); 
          break; 

         default: 
          Info->lpszMoreInfoLink = NULL; 
          break; 
        } 
       }    
       else 
       { 
        Info->lpszMoreInfoLink = NULL; 
       } 

       fReturn = TRUE; 

       break; // Break from for loop. 
      } // lstrcmp SPC_SP_OPUS_INFO_OBJID     
     } // for 
    } 
    __finally 
    { 
     if (OpusInfo != NULL) LocalFree(OpusInfo);  
    } 

    return fReturn; 
} 

BOOL GetDateOfTimeStamp(PCMSG_SIGNER_INFO pSignerInfo, SYSTEMTIME *st) 
{ 
    BOOL fResult; 
    FILETIME lft, ft; 
    DWORD dwData; 
    BOOL fReturn = FALSE; 

    // Loop through authenticated attributes and find 
    // szOID_RSA_signingTime OID. 
    for (DWORD n = 0; n < pSignerInfo->AuthAttrs.cAttr; n++) 
    {   
     if (lstrcmpA(szOID_RSA_signingTime, 
        pSignerInfo->AuthAttrs.rgAttr[n].pszObjId) == 0) 
     {    
      // Decode and get FILETIME structure. 
      dwData = sizeof(ft); 
      fResult = CryptDecodeObject(ENCODING, 
         szOID_RSA_signingTime, 
         pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].pbData, 
         pSignerInfo->AuthAttrs.rgAttr[n].rgValue[0].cbData, 
         0, 
         (PVOID)&ft, 
         &dwData); 
      if (!fResult) 
      { 
       _tprintf(_T("CryptDecodeObject failed with %x\n"), 
        GetLastError()); 
       break; 
      } 

      // Convert to local time. 
      FileTimeToLocalFileTime(&ft, &lft); 
      FileTimeToSystemTime(&lft, st); 

      fReturn = TRUE; 

      break; // Break from for loop. 

     } //lstrcmp szOID_RSA_signingTime 
    } // for 

    return fReturn; 
} 

BOOL GetTimeStampSignerInfo(PCMSG_SIGNER_INFO pSignerInfo, PCMSG_SIGNER_INFO *pCounterSignerInfo) 
{ 
    PCCERT_CONTEXT pCertContext = NULL; 
    BOOL fReturn = FALSE; 
    BOOL fResult;  
    DWORD dwSize; 

    __try 
    { 
     *pCounterSignerInfo = NULL; 

     // Loop through unathenticated attributes for 
     // szOID_RSA_counterSign OID. 
     for (DWORD n = 0; n < pSignerInfo->UnauthAttrs.cAttr; n++) 
     { 
      if (lstrcmpA(pSignerInfo->UnauthAttrs.rgAttr[n].pszObjId, 
         szOID_RSA_counterSign) == 0) 
      { 
       // Get size of CMSG_SIGNER_INFO structure. 
       fResult = CryptDecodeObject(ENCODING, 
          PKCS7_SIGNER_INFO, 
          pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData, 
          pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData, 
          0, 
          NULL, 
          &dwSize); 
       if (!fResult) 
       { 
        _tprintf(_T("CryptDecodeObject failed with %x\n"), 
         GetLastError()); 
        __leave; 
       } 

       // Allocate memory for CMSG_SIGNER_INFO. 
       *pCounterSignerInfo = (PCMSG_SIGNER_INFO)LocalAlloc(LPTR, dwSize); 
       if (!*pCounterSignerInfo) 
       { 
        _tprintf(_T("Unable to allocate memory for timestamp info.\n")); 
        __leave; 
       } 

       // Decode and get CMSG_SIGNER_INFO structure 
       // for timestamp certificate. 
       fResult = CryptDecodeObject(ENCODING, 
          PKCS7_SIGNER_INFO, 
          pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].pbData, 
          pSignerInfo->UnauthAttrs.rgAttr[n].rgValue[0].cbData, 
          0, 
          (PVOID)*pCounterSignerInfo, 
          &dwSize); 
       if (!fResult) 
       { 
        _tprintf(_T("CryptDecodeObject failed with %x\n"), 
         GetLastError()); 
        __leave; 
       } 

       fReturn = TRUE; 

       break; // Break from for loop. 
      }   
     } 
    } 
    __finally 
    { 
     // Clean up. 
     if (pCertContext != NULL) CertFreeCertificateContext(pCertContext); 
    } 

    return fReturn; 
} 
+0

実際、CryptMsgGetParamはCMSG_SIGNER_INFO_PARAMのために指定しています「というメッセージの署名者のすべての署名者の情報を取得するには、様々なCryptMsgGetParamを呼び出しますdwIndexは0から署名者の数-1を引いた値です。あなたのコードはこのオプションを使用していないようですが、CMSG_SIGNER_INFO_PARAM呼び出しでdwIndexを1に設定した場合の戻り値(とGetLastError())は何ですか? –

+0

@TonPlooij:それは私のコードではありません。これはKB323809の在庫例です。私は 'CMSG_SIGNER_COUNT_PARAM'で' CryptMsgGetParam'を呼び出すと、署名者は1人しかいないようです。そして、もし私が 'CryptMsgGetParam'を0より大きいインデックスに対して' CMSG_SIGNER_INFO_PARAM'と呼ぶと、それは 'インデックス値が有効ではない'エラーコード '0x80091008 'で失敗するでしょう。 – c00000fd

+0

他の" count "ドキュメント( 'CMSG_ATTR_CERT_COUNT_PARAM'、' CMSG_CERT_COUNT_PARAM'など)にあります。それらのいずれかが3を返しますか? –

答えて

1

Authenticodeのストア二次署名を:明らかに、この例では3のように、より多くを持っています。主な署名から

は、以下のためUnauthenticatedAttribueを検索:

は//属性が

szOID_NESTED_SIGNATUREを定義PKCS7

をエンコードオクテットである "1.3.6.1.4.1.311.2.4.1"

示しますこの属性のエンコードされたオブジェクトは、完全なPKCS 7署名者です。

ありがとうございました。

4

Daniel Sieの回答に加えて、

LNestedMsg := CryptMsgOpenToDecode(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 0, 0, 0, nil, 0); 
    CryptMsgUpdate(LNestedMsg, LFindedAttr.rgValue.pbData, LFindedAttr.rgValue.cbData, True); 
    CryptMsgGetParam(LNestedMsg, CMSG_SIGNER_INFO_PARAM, 0, nil, @LSize); 
    CryptMsgGetParam(LNestedMsg, CMSG_SIGNER_INFO_PARAM, 0, LNestedSignerInfo, @LSize); 

取得CMSG_SIGNER_INFO(LNestedSignerInfo)入れ子になっている:属性(szOID_NESTED_SIGNATURE)は、次の手順でデコードする必要がCMSG_SIGNER_INFOを含んでいるでしょう(これはDelphiのコードですが、感覚がクリアされている)が見つかり

署名(この場合はSHA2署名)。

その署名のタイムスタンプ情報(RFC3161)を取得するには、pszObjId = szOID_RFC3161_counterSign(1.3.6.1.4.1.311.3.3.1)でUnauthenticated属性を検索します。

Found属性には、前述の手順(CryptMsgOpenToDecode、CryptMsgUpdate、CryptMsgGetParam)でデコードする必要があるタイムスタンプカウンタシグネチャのCMSG_SIGNER_INFOが含まれます。

ネストされたシグネチャまたはタイムスタンプカウンタシグネチャのCERT_CONTEXTは、対応するHCRYPTMSG(CryptMsgOpenToDecodeの結果)から取得されたストアで検索する必要があります。

LNestedStore := CertOpenStore(CERT_STORE_PROV_MSG, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, 0, 0, LNestedMsg); 
    LTimeStampStore := CertOpenStore(CERT_STORE_PROV_MSG, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, 0, 0, LTimeStampMsg); 

szOID_RFC3161_counterSign属性をデコードする例:

LNestedSignerAttr := LNestedSigner.UnauthAttrs.rgAttr; 
for I := 0 to LNestedSigner.UnauthAttrs.cAttr - 1 do 
begin 
    if SameText(string(LNestedSignerAttr.pszObjId), szOID_RFC3161_counterSign) then 
    begin 
    LNestedTimeStampMsg := CryptMsgOpenToDecode(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 0, 0, 0, nil, nil); 
    if not Assigned(LNestedTimeStampMsg) then 
     RaiseLastOSError; 
    try 
     if not CryptMsgUpdate(LNestedTimeStampMsg, LNestedSignerAttr.rgValue.pbData, LNestedSignerAttr.rgValue.cbData, True) then 
     RaiseLastOSError; 

     if not CryptMsgGetParam(LNestedTimeStampMsg, CMSG_SIGNER_INFO_PARAM, 0, nil, @LSize) then 
     RaiseLastOSError; 
     GetMem(LTimeStampSigner, LSize); 
     try 
     if not CryptMsgGetParam(LNestedTimeStampMsg, CMSG_SIGNER_INFO_PARAM, 0, LTimeStampSigner, @LSize) then 
      RaiseLastOSError; 

     LAttr := LTimeStampSigner.AuthAttrs.rgAttr; 
     for J := 0 to LTimeStampSigner.AuthAttrs.cAttr - 1 do 
     begin 
      if SameText(string(LAttr.pszObjId), szOID_RSA_signingTime) then 
      begin 
      LSize := SizeOf(LFileTime); 
      if not CryptDecodeObject(X509_ASN_ENCODING or PKCS_7_ASN_ENCODING, 
       szOID_RSA_signingTime, LAttr.rgValue.pbData, LAttr.rgValue.cbData, 0, @LFileTime, @LSize) then 
       RaiseLastOSError; 

      if FileTimeToLocalFileTime(@LFileTime, LLocalFileTime) 
       and FileTimeToSystemTime(@LLocalFileTime, LSystemTime) then 
       SHA2TimeStamp := SystemTimeToDateTime(LSystemTime) 
      else 
       SHA2TimeStamp := 0; 

      end; 
      Inc(LAttr); 
     end; 

     finally 
     FreeMem(LTimeStampSigner); 
     end; 
    finally 
     if not CryptMsgClose(LNestedTimeStampMsg) then 
     RaiseLastOSError; 
    end; 
    end; 

    Inc(LNestedSignerAttr); 
end; 
+0

szOID_RFC3161_counterSign属性をどのように解読しますか? – Alex

+0

同様に。 –

+0

私は間違ったキーワードでグーグルであるかもしれませんが、その上の任意のドキュメントを見つけることができません。何らかのASN.1エンコーディングのようですか? – Alex

関連する問題