2014-07-22 10 views
11

मैं कोड लिखने की कोशिश कर रहा हूं जो डीएलएल या EXEs से हस्ताक्षर (प्रमाण पत्र) पढ़ता है। अधिकांश डीएलएल या EXEs में केवल एक हस्ताक्षर होता है, और मेरा कोड सही ढंग से इस हस्ताक्षर से जुड़े सभी प्रमाण पत्र पढ़ता है। अधिक विशेष रूप से यह हस्ताक्षर प्रमाण पढ़ता है, यह जारीकर्ता (रूट नहीं) है, काउंटरसिग्नलिंग प्रमाण (टाइमस्टैम्प के साथ) और इसके जारीकर्ता (रूट नहीं)। मेरे पास सी ++ और सी # में 2 नमूना कार्यक्रम हैं, वे दोनों एक ही कॉर्ट लौटाते हैं। यह सी # कोड है, सी ++ 100 बार लंबे समय तक :)निष्पादन योग्य फ़ाइल से कई हस्ताक्षर पढ़ना

static void Main(string[] args) 
{ 
    X509Certificate2Collection collection = new X509Certificate2Collection(); 
    collection.Import(args[0]); 
} 

है लेकिन DLLs 2 हस्ताक्षर है, फ़ाइल गुण में दिखाया गया है/डिजिटल हस्ताक्षर, उदाहरण के लिए C देखते हैं: \ Program Files (x86) \ Microsoft SQL सर्वर \ 80 \ उपकरण \ Binn \ Msvcr71.dll:

File properties and digital signatures for msvcr71.dll

इस DLL मेरे कोड केवल पहले हस्ताक्षर से संबद्ध प्रमाणपत्रों को पढ़ता है।

मैंने साइनटोल का उपयोग करने की भी कोशिश की, और यह मेरे कोड के समान जानकारी देता है: पहला प्रमाणपत्र (इसके पथ के साथ), और काउंटरसिग्नेचर (इसके पथ के साथ)। लेकिन अंत में त्रुटि भी ध्यान दें।

C:\Windows>signtool verify /d /v "C:\Program Files (x86)\Microsoft SQL Server\80\Tools\Binn\msvcr71.dll" 

Verifying: C:\Program Files (x86)\Microsoft SQL Server\80\Tools\Binn\msvcr71.dll 
Signature Index: 0 (Primary Signature) 
Hash of file (sha1): 33BBCCF6326276B413A1ECED1BF7842A6D1DDA07 

Signing Certificate Chain: 
Issued to: Microsoft Root Certificate Authority 
Issued by: Microsoft Root Certificate Authority 
Expires: Sun May 09 19:28:13 2021 
SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072 

    Issued to: Microsoft Code Signing PCA 
    Issued by: Microsoft Root Certificate Authority 
    Expires: Wed Jan 25 19:32:32 2017 
    SHA1 hash: FDD1314ED3268A95E198603BA8316FA63CBCD82D 

     Issued to: Microsoft Corporation 
     Issued by: Microsoft Code Signing PCA 
     Expires: Fri Feb 01 18:49:17 2013 
     SHA1 hash: 8849D1C0F147A3C8327B4038783AEC3E06C76F5B 

The signature is timestamped: Sat Feb 11 14:03:12 2012 
Timestamp Verified by: 
Issued to: Microsoft Root Certificate Authority 
Issued by: Microsoft Root Certificate Authority 
Expires: Sun May 09 19:28:13 2021 
SHA1 hash: CDD4EEAE6000AC7F40C3802C171E30148030C072 

    Issued to: Microsoft Time-Stamp PCA 
    Issued by: Microsoft Root Certificate Authority 
    Expires: Sat Apr 03 09:03:09 2021 
    SHA1 hash: 375FCB825C3DC3752A02E34EB70993B4997191EF 

     Issued to: Microsoft Time-Stamp Service 
     Issued by: Microsoft Time-Stamp PCA 
     Expires: Thu Oct 25 16:42:17 2012 
     SHA1 hash: FC33104FAE31FB538749D5F2D17FA0ECB819EAE5 

SignTool Error: The signing certificate is not valid for the requested usage. 
    This error sometimes means that you are using the wrong verification 
    policy. Consider using the /pa option. 

Number of files successfully Verified: 0 
Number of warnings: 0 
Number of errors: 1 

2 प्रश्न हैं: - दूसरे हस्ताक्षर का उद्देश्य है क्या - इसे पढ़ने के (अब तक केवल Windows Explorer फ़ाइल संपत्ति संवाद यह दिखा सकते हैं)।

धन्यवाद!

+0

कारण आप उन दोहरी हस्ताक्षर देखते हैं क्योंकि [माइक्रोसॉफ्ट का बहिष्कार कर रहा है] है (http://social.technet.microsoft.com/wiki/contents/articles/32288.windows-enforcement-of-authenticode-code -साइनिंग-एंड-टाइमस्टैम्पिंग.एएसपीएक्स) एसएचए -1 के हस्ताक्षर [एसएए -1 '[अपर्याप्त टकराव प्रतिरोध] के कारण हस्ताक्षर (http://crypto.stackexchange.com/questions/845/what-is-wrong-with-using- SHA1 में डिजिटल हस्ताक्षर-क्यों-है एक मजबूत-हैश-कामकाज)। वे पिछड़े संगतता के लिए आज छोड़ दिए गए हैं। – ahmd0

उत्तर

0

The signature is timestamped: Sat Feb 11 14:03:12 2012 

और

Issued to: Microsoft Time-Stamp Service 

मैं दूसरे हस्ताक्षर/प्रमाण पत्र ग्रहण करता हूँ को देखते हुए time-stamping फ़ाइलों के लिए प्रयोग किया जाता है। यह अच्छी तरह से हो सकता है कि एमएस में दो अलग संगठनात्मक इकाइयां हैं, जिनमें से एक कोड को अपनी ईमानदारी को स्वीकार करने के लिए संकेत करता है और दूसरा (बाद में) अपने स्वयं के प्रमाण पत्र के साथ कोड को फिर से संकेत करता है, विशेष रूप से सुरक्षित समय-समय पर फ़ाइल को मुद्रित करने के लिए।

प्रमाणपत्र कुछ उपयोगों के लिए बनाए और सौंपा जा सकता है। समय-मुद्रांकन के लिए उपयोग किए जाने वाले प्रमाण पत्र को इस तरह चिह्नित किया जा सकता है, इसलिए signtool है, जब यह समय-मुद्रांकन प्रमाण पत्र का सामना करता है, तो त्रुटि देता है क्योंकि डिफ़ॉल्ट रूप से यह कोड प्रामाणिकता/अखंडता सत्यापन के लिए प्रमाणपत्र की अपेक्षा करता है और समय-मुद्रांकन के लिए एक नहीं।

+0

नहीं, डिजिटल हस्ताक्षर टैब में दूसरा प्रमाणपत्र केवल टाइमस्टैम्प नहीं है। प्रत्येक हस्ताक्षर (दो में से) में इसके साथ जुड़े 6 प्रमाण पत्र हैं: हस्ताक्षर के लिए पथ बनाने के लिए 3 कर्ट, और 3 सिग्नलोल के आउटपुट में दिखाए गए टाइमस्टैम्प के लिए। मैं सहमत हूं कि दो या दो से अधिक हस्ताक्षर संभव हो सकते हैं (प्रश्न यह है कि उन दोनों को कौन पढ़ा जाए?), लेकिन टाइमस्टैम्प हस्ताक्षर हस्ताक्षर के समय लागू किया जाना चाहिए, टाइमस्टैम्प प्रमाण का पूरा उद्देश्य यह सुनिश्चित करना है कि यह हस्ताक्षर का समय है । – Dima

+0

बिल्कुल यकीन नहीं है कि आपका बिंदु क्या है। हम दोनों समझते हैं कि दो हस्ताक्षर हैं, जिनमें से एक बाइनरी ("जारी किए गए: माइक्रोसॉफ्ट कोड साइनिंग पीसीए") की लेखनी को मान्य करने के लिए कार्य करता है और दूसरा एक विश्वसनीय टाइमस्टैम्प स्थापित करने के लिए ("जारी किया गया: माइक्रोसॉफ्ट टाइम- स्टाम्प सेवा ")। दो हस्ताक्षर विभिन्न उद्देश्यों को पूरा करते हैं और शायद एमएस संगठन के भीतर विभिन्न संस्थाओं द्वारा बनाए जाते हैं। बेशक, प्रत्येक हस्ताक्षर एक टाइमस्टैम्प भालू है, लेकिन टाइमस्टैम्पिंग अथॉरिटी द्वारा जारी एक विश्वसनीय टाइमस्टैम्प का 'सामान्य' हस्ताक्षर से अलग अर्थ होता है, विकिपीडिया लिंक देखें। – JimmyB

+0

एससीन शॉट में दूसरे टैब पर 2 साइनआउट हैं, एक sha1 है, दूसरा sha256 है। साइनटोल और मेरा कोड उनमें से केवल एक को पढ़ सकता है, sha1। इस हस्ताक्षर (sha1) में इसके साथ जुड़े 6 प्रमाण पत्र हैं, जो साइनटोल आउटपुट में प्रदर्शित होते हैं। मैं फ़ाइल प्रॉपर्टी डायलॉग में sha256 से जुड़े 6 और प्रमाणपत्र देख सकता हूं (यदि आप विवरण बटन का उपयोग करने में ड्रिल करते हैं, लेकिन न तो साइनटोल और न ही मेरा कोड उन्हें दिखा सकता है। दूसरे शब्दों में: यदि आप टाइमस्टैम्प हस्ताक्षर (काउंटरसिग्नेचर) को अलग-अलग हस्ताक्षर के रूप में देखते हैं, इस डीएलएल में कुल 4 हस्ताक्षर हैं। लेकिन साइनटोल केवल 2. – Dima

13

खुदाई और विभिन्न चीजों की कोशिश करने के बाद मुझे पता चला कि WinVerifyTrust फ़ंक्शन एकाधिक एम्बेडेड प्रमाणपत्र पढ़ सकता है। फ़ंक्शन नाम को अनदेखा करें, इसका उपयोग कई चीजों के लिए किया जा सकता है, यह एक सार्वभौमिक कार्य है।

WinVerifyTrust संरचना WINTRUST_DATA अपने इन/आउट पैरामीटर में से एक के रूप में लेता है। डॉक्स का कहना है कि यह IN है, लेकिन इसका उपयोग वापस जानकारी वापस करने के लिए भी किया जाता है।

WINTRUST_DATA क्षेत्र pSignatureSettings है, जो एक और struct, WINTRUST_SIGNATURE_SETTINGS के लिए सूचक है है। इस स्टैक्ट में dwFlags फ़ील्ड है जो नियंत्रित करता है कि WinVerifyTrust द्वारा कौन सी जानकारी लौटा दी जाएगी।

सबसे पहले आप WINTRUST_SIGNATURE_SETTINGS::dwFlags = WSS_GET_SECONDARY_SIG_COUNT साथ WinVerifyTrust माध्यमिक हस्ताक्षर है, जो क्षेत्र WINTRUST_SIGNATURE_SETTINGS::cSecondarySigs में दिया जाता है की संख्या वापस पाने के लिए कहते हैं। ध्यान दें कि यदि आपकी फ़ाइल 2 हस्ताक्षर, है cSecondarySigs हो जाएगा 1.

फिर पाश for (int i = 0; i <= cSecondarySigs; i++) में आप WINTRUST_SIGNATURE_SETTINGS::dwFlags = WSS_VERIFY_SPECIFIC और WINTRUST_SIGNATURE_SETTINGS::dwIndex = i साथ WinVerifyTrust कहते हैं।

प्रत्येक WinVerifyTrust इस कॉल के अनुक्रम द्वारा WINTRUST_DATA::hWVTStateData से कॉल प्राप्त कर सकते हैं प्रमाण पत्र की जानकारी (countersignatures सहित) के बाद:

WTHelperProvDataFromStateData(hWVTStateData); 
WTHelperGetProvSignerFromChain(...); 
WTHelperGetProvCertFromChain(...); 

मैं नेट एपीआई में ज्यादा खुदाई नहीं था, लेकिन ऐसा लगता है कि यह पढ़ सकते हैं केवल पहला हस्ताक्षर। ध्यान दें कि WINTRUST_SIGNATURE_SETTINGS, जो एकाधिक हस्ताक्षर पढ़ने की कुंजी प्रतीत होता है, विंडोज 8 में जोड़ा गया था, इसलिए पुराने ओएस पर आप कम से कम एमएस एपीआई के साथ इसे पढ़ने में सक्षम नहीं होंगे।

+1

यह वही है जो मैं खोज रहा हूं। धन्यवाद! –

0

SignTool.exe का नवीनतम संस्करण एकाधिक हस्ताक्षरों से निपट सकता है।

एक/डीएस स्विच का उपयोग करना था। यह आपको हस्ताक्षर सूचकांक का चयन करने देता है।

बेहतर अभी तक, यहां एक शानदार सी # उदाहरण है जो एकाधिक हस्ताक्षर पढ़ और सत्यापित करेगा। Code signing an executable twice

4

दीमा के जवाब विस्तार, मैं एक नमूना कोड सभी एम्बेडेड (और नेस्टेड) ​​पत्ती जांच करने का तरीका प्रमाण पत्र (प्रमाणपत्र श्रृंखला के बीच में नहीं) को दर्शाता है जो उपलब्ध कराना चाहते हैं।

BOOL CheckCertificateIssuer(HANDLE hWVTStateData, const std::set<CString> &stValidIssuers) 
{ 
    CRYPT_PROVIDER_DATA *pCryptProvData = WTHelperProvDataFromStateData(hWVTStateData); 
    CRYPT_PROVIDER_SGNR *pSigner = WTHelperGetProvSignerFromChain(pCryptProvData, 0, FALSE, 0); 
    CRYPT_PROVIDER_CERT *pCert = WTHelperGetProvCertFromChain(pSigner, 0); 

    CString sIssuer; 
    int nLength = CertGetNameString(pCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, NULL, 0); 
    if (!nLength) 
    { 
     ASSERT(FALSE && "Cannot get the length of the Issuer string"); 
     return FALSE; 
    } 

    if (!CertGetNameString(pCert->pCert, CERT_NAME_SIMPLE_DISPLAY_TYPE, CERT_NAME_ISSUER_FLAG, NULL, sIssuer.GetBuffer(nLength), nLength)) 
    { 
     ASSERT(FALSE && "Cannot get the Issuer string"); 
     return FALSE; 
    } 
    sIssuer.ReleaseBuffer(nLength); 
    if (stValidIssuers.find(sIssuer) == stValidIssuers.end()) 
    { 
     ASSERT(FALSE && "Certificate issuer is invalid"); 
     return FALSE; 
    } 
    return TRUE; 
} 
BOOL CheckCertificate(CString filename) 
{ 
    std::set<CString> stValidIssuers; 
    stValidIssuers.insert(L"VeriSign Class 3 Code Signing 2010 CA"); 
    stValidIssuers.insert(L"Symantec Class 3 SHA256 Code Signing CA"); 

    bool UseStrongSigPolicy = false; 

    DWORD Error = ERROR_SUCCESS; 
    bool WintrustCalled = false; 
    GUID GenericActionId = WINTRUST_ACTION_GENERIC_VERIFY_V2; 
    WINTRUST_DATA WintrustData = {}; 
    WINTRUST_FILE_INFO FileInfo = {}; 
    WINTRUST_SIGNATURE_SETTINGS SignatureSettings = {}; 
    CERT_STRONG_SIGN_PARA StrongSigPolicy = {}; 

    // Setup data structures for calling WinVerifyTrust 
    WintrustData.cbStruct = sizeof(WINTRUST_DATA); 
    WintrustData.dwStateAction = WTD_STATEACTION_VERIFY; 
    WintrustData.dwUIChoice = WTD_UI_NONE; 
    WintrustData.fdwRevocationChecks = WTD_REVOKE_NONE; 
    WintrustData.dwUnionChoice = WTD_CHOICE_FILE; 

    FileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO_); 
    FileInfo.pcwszFilePath = filename; 
    WintrustData.pFile = &FileInfo; 

    // 
    // First verify the primary signature (index 0) to determine how many secondary signatures 
    // are present. We use WSS_VERIFY_SPECIFIC and dwIndex to do this, also setting 
    // WSS_GET_SECONDARY_SIG_COUNT to have the number of secondary signatures returned. 
    // 
    SignatureSettings.cbStruct = sizeof(WINTRUST_SIGNATURE_SETTINGS); 
    SignatureSettings.dwFlags = WSS_GET_SECONDARY_SIG_COUNT | WSS_VERIFY_SPECIFIC; 
    SignatureSettings.dwIndex = 0; 
    WintrustData.pSignatureSettings = &SignatureSettings; 

    if (UseStrongSigPolicy != false) 
    { 
     StrongSigPolicy.cbSize = sizeof(CERT_STRONG_SIGN_PARA); 
     StrongSigPolicy.dwInfoChoice = CERT_STRONG_SIGN_OID_INFO_CHOICE; 
     StrongSigPolicy.pszOID = szOID_CERT_STRONG_SIGN_OS_CURRENT; 
     WintrustData.pSignatureSettings->pCryptoPolicy = &StrongSigPolicy; 
    } 
    BOOL bResult = E_NOT_SET; 
    TRACE(L"Verifying primary signature... "); 
    Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData); 
    WintrustCalled = true; 
    if (Error == ERROR_SUCCESS) 
    { 
     if (CheckCertificateIssuer(WintrustData.hWVTStateData, stValidIssuers)) 
     { 
      if (bResult == E_NOT_SET) 
       bResult = TRUE; 
     } 
     else 
     { 
      bResult = FALSE; 
     } 

     TRACE(L"Success!\n"); 

     TRACE(L"Found %d secondary signatures\n", WintrustData.pSignatureSettings->cSecondarySigs); 

     // Now attempt to verify all secondary signatures that were found 
     for (DWORD x = 1; x <= WintrustData.pSignatureSettings->cSecondarySigs; x++) 
     { 
      TRACE(L"Verify secondary signature at index %d... ", x); 

      // Need to clear the previous state data from the last call to WinVerifyTrust 
      WintrustData.dwStateAction = WTD_STATEACTION_CLOSE; 
      Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData); 
      if (Error != ERROR_SUCCESS) 
      { 
       //No need to call WinVerifyTrust again 
       WintrustCalled = false; 
       TRACE(L"%s", utils::error::getText(Error)); 
       ASSERT(FALSE); 
       break; 
      } 

      WintrustData.hWVTStateData = NULL; 

      // Caller must reset dwStateAction as it may have been changed during the last call 
      WintrustData.dwStateAction = WTD_STATEACTION_VERIFY; 
      WintrustData.pSignatureSettings->dwIndex = x; 
      Error = WinVerifyTrust(NULL, &GenericActionId, &WintrustData); 
      if (Error != ERROR_SUCCESS) 
      { 
       TRACE(L"%s", utils::error::getText(Error)); 
       ASSERT(FALSE); 
       break; 
      } 

      if (CheckCertificateIssuer(WintrustData.hWVTStateData, stValidIssuers)) 
      { 
       if (bResult == E_NOT_SET) 
        bResult = TRUE; 
      } 
      else 
      { 
       bResult = FALSE; 
      } 


      TRACE(L"Success!\n"); 
     } 
    } 
    else 
    { 
     TRACE(utils::error::getText(Error)); 
     ASSERT(FALSE); 
    } 

    // 
    // Caller must call WinVerifyTrust with WTD_STATEACTION_CLOSE to free memory 
    // allocate by WinVerifyTrust 
    // 
    if (WintrustCalled != false) 
    { 
     WintrustData.dwStateAction = WTD_STATEACTION_CLOSE; 
     WinVerifyTrust(NULL, &GenericActionId, &WintrustData); 
    } 

    return bResult; 

} 
संबंधित मुद्दे