2010-01-05 5 views
9

यह question 1072540, 'WinVerifyTrust to check for a specific signature?' पर एक फॉलोअप प्रश्न है।यह सत्यापित करने के लिए कि मेरे संगठन ने एक विश्वसनीय विंडोज बाइनरी पर हस्ताक्षर किए हैं?

bool TrustedByUs(std::string pathToBinary, std::string pathToPublicKey) 

विचार है कि हम इस समारोह एक द्विआधारी .dll या exe फ़ाइल है कि कर दिया गया है करने के लिए एक रास्ता देना है:

मैं एक सी लिखना चाहते ++ समारोह यह फ़ॉर्म के 'TrustedByUs' कहते चलें एक डिजिटल हस्ताक्षर के साथ हस्ताक्षर किए। 'PathToPublicKey' स्ट्रिंग हमारे विशेष हस्ताक्षर प्रमाणपत्र की एक जघन्य कुंजी का मार्ग है।

http://support.microsoft.com/kb/323809 में कोड का उपयोग करना यह सत्यापित करने के लिए काफी सरल है कि 'pathToBinary' फ़ाइल वास्तव में ऑपरेटिंग सिस्टम द्वारा भरोसा है।

अब मैं प्रश्न 1072540 के लेखक के समान स्थान पर हूं, मुझे पता है कि ओएस इस बाइनरी के हस्ताक्षरकर्ता पर भरोसा करता है, लेकिन मैं जानना चाहता हूं कि मेरे संगठन की आरएसए कुंजी बाइनरी पर हस्ताक्षर करने वाली है या नहीं।

KB323809 दिखाता है कि हमारी बाइनरी फ़ाइल में एम्बेडेड प्रमाणपत्र से स्ट्रिंग कैसे निकालें। यह उदाहरण दिखाता है कि GetProgAndPublisherInfo फ़ंक्शन में हस्ताक्षर प्रमाणपत्र से स्ट्रिंग कैसे निकालें, लेकिन प्रमाणपत्र के सत्यापन के लिए स्ट्रिंग मैच का उपयोग करके मैं असहज हूं।

मैं क्या करना चाहता हूं एम्बेडेड हस्ताक्षर से सार्वजनिक कुंजी निकालें और इसे सार्वजनिक कुंजी से तुलना करें जो कि मेरी बाइनरी फ़ाइल पर पहली बार हस्ताक्षर किए गए निजी कुंजी से मेल खाती है।

CryptMsgGetParam के लिए प्रलेखन का कहना है कि CMSG_SIGNER_CERT_ID_PARAM पैरामीटर 'हस्ताक्षरकर्ता की सार्वजनिक कुंजी की पहचान करने के लिए आवश्यक संदेश हस्ताक्षरकर्ता पर जानकारी देता है'। मैं इस कुंजी के साथ प्रमाणपत्र का सीरियल नंबर प्राप्त करने में सफल हूं। मेरे कोड इस तरह दिखता है:

// Get message handle and store handle from the signed file. 
fResult = CryptQueryObject(CERT_QUERY_OBJECT_FILE, 
    L"C:\\Program Files\\MySignedProgram.exe", 
    CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, 
    CERT_QUERY_FORMAT_FLAG_BINARY, 
    0, &dwEncoding, &dwContentType, &dwFormatType, &hStore, &hMsg, NULL); 

// Get the public key information about the signer 
// First get the size 
DWORD dwCertIdSize(0); 
fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 
    0, NULL, &dwCertIdSize); 
BYTE* pCertId = new BYTE(dwCertIdSize); 
::ZeroMemory(pCertId,dwCertIdSize); 

// Now get the cert info 
fResult = CryptMsgGetParam(hMsg, CMSG_SIGNER_CERT_ID_PARAM, 
    0, (PVOID)pCertId, &dwCertIdSize); 

if(fResult) 
{  
    CERT_ID* pId = (CERT_ID*)pCertId; 
    pId->HashId; 
    pId->dwIdChoice; 
    pId->IssuerSerialNumber; // Valid serial number (reversed) 
    pId->KeyId; 
    _tprintf("pid\n"); 
} 

यह जो मैं चाहता के करीब है, लेकिन वास्तव में मुझे लगता है कि लक्ष्य पर हस्ताक्षर किए बाइनरी फ़ाइल वास्तव में मेरी विशेष जनता के साथ बनाया गया था सत्यापित करने के लिए हस्ताक्षर करने के प्रमाण पत्र की सार्वजनिक कुंजी का उपयोग करना चाहते/निजी कुंजी जोड़ी।

CMSG_ENCRYPTED_DIGEST ध्वज का उपयोग करते हुए इस कोड को सफल होता है:

// Get digest which was encrypted with the private key 
DWORD digestSize(0); 
fResult = CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, NULL, &digestSize); 

BYTE* pDigest = new BYTE[digestSize]; 

// Next CryptMsgGetParam call succeds, 
// pDigest looks valid, can I use this to confirm my public key 
// was used to sign MySignedProgram.exe ? 
fResult = CryptMsgGetParam(hMsg, CMSG_ENCRYPTED_DIGEST, 0, pDigest, &digestSize); 

निष्कर्ष सवाल: CryptQueryObject द्वारा की खोज प्रमाणपत्र जानकारी, क्या तकनीक मैं यह सुनिश्चित करें कि लक्ष्य फ़ाइल में तथ्य का उपयोग करके हस्ताक्षरित था इस्तेमाल किया जाना चाहिए यह देखते हुए निजी कुंजी जो उपरोक्त कोड निष्पादित होने पर मेरे लिए उपलब्ध सार्वजनिक कुंजी से मेल खाती है?

उत्तर

7

आप इसके बजाय CMSG_SIGNER_INFO_PARAM चाहते हैं।

आप प्रमाणपत्र संग्रह CryptQueryObject द्वारा लौटाए में प्रमाण पत्र देख कर पूरे प्रमाण पत्र प्राप्त करने के लिए इस का उपयोग कर सकते हैं:

CryptMsgGetParam(hMsg, 
       CMSG_SIGNER_INFO_PARAM, 
       0, 
       NULL, 
       &dwSignerInfo); 
PCMSG_SIGNER_INFO pSignerInfo = (PCMSG_SIGNER_INFO) malloc(dwSignerInfo); 
CryptMsgGetParam(hMsg, 
       CMSG_SIGNER_INFO_PARAM, 
       0, 
       pSignerInfo, 
       &dwSignerInfo); 

PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(hStore, 
              ENCODING, 
              0, 
              CERT_FIND_SUBJECT_CERT, 
              (PVOID)pSignerInfo, 
              NULL); 
// Compare with your certificate: 
// - check pCertContext->pbCertEncoded (length is pCertContext->cbCertEncoded) 

// *OR* 
// Compare with your public-key: 
// - check pCertContext->pCertInfo->SubjectPublicKeyInfo.Algorithm and 
// pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey 
+0

धन्यवाद Rasmus, लेकिन मैं अभी भी एक सा संदेह में हूँ। CMSG_SIGNER_INFO स्टैक्ट में SubjectPublicKeyInfol सदस्य शामिल नहीं है। –

+0

क्षमा करें, मैंने CMSG_SIGNER_INFO और CERT_INFO संरचना को मिश्रित किया है। जवाब अब सुधार होना चाहिए। –

+0

धन्यवाद रasmस, मुझे इस परियोजना में सहायक होने के लिए CERT_NAME_SIMPLE_DISPLAY_TYPE ध्वज के साथ CertGetNameString एपीआई भी मिला। –