Wie überprüfe ich, ob meine Organisation eine vertrauenswürdige Windows-Binärdatei signiert hat?

Dies ist eine Folgefrage zuFrage 1072540, "WinVerifyTrust, um nach einer bestimmten Signatur zu suchen?".

Ich möchte eine C ++ - Funktion schreiben. Nennen wir sieTrustedByUs des Formulars:

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

Die Idee ist, dass wir dieser Funktion einen Pfad zu einer binären DLL- oder EXE-Datei geben, die mit einer digitalen Signatur signiert wurde. DaspathToPublicKey string ist der Pfad zu einem öffentlichen Schlüssel unseres speziellen Signaturzertifikats.

Verwenden Sie den Code inhttp://support.microsoft.com/kb/323809 Es ist ziemlich einfach zu überprüfen, dass diepathToBinary Die Datei wird vom Betriebssystem als vertrauenswürdig eingestuft.

Jetzt bin ich am selben Ort wie der Verfasser der Frage 1072540. Ich weiß, dass das Betriebssystem dem Unterzeichner dieser Binärdatei vertraut, aber ich möchte wissen, ob der RSA-Schlüssel meiner Organisation derjenige ist, der die Binärdatei signiert hat.

Das KB323809 zeigt, wie die Zeichenfolgen aus dem in unserer Binärdatei eingebetteten Zertifikat extrahiert werden. In diesem Beispiel wird gezeigt, wie Zeichenfolgen aus dem Signaturzertifikat extrahiert werdenGetProgAndPublisherInfo Funktion, aber es ist mir unangenehm, eine Zeichenfolgenübereinstimmung zum Überprüfen des Zertifikats zu verwenden.

Was ich tun möchte, ist, den öffentlichen Schlüssel aus der eingebetteten Signatur zu extrahieren und ihn mit dem öffentlichen Schlüssel zu vergleichen, der dem privaten Schlüssel entspricht, der meine Binärdatei an erster Stelle signiert hat.

Die Dokumentation fürCryptMsgGetParam sagt, dass dieCMSG_SIGNER_CERT_ID_PARAM Parameter 'Gibt Informationen zu einem Unterzeichner der Nachricht zurück, die zur Identifizierung des öffentlichen Schlüssels des Unterzeichners erforderlich sind'. Mit diesem Schlüssel kann ich die Seriennummer des Zertifikats ermitteln. Mein Code sieht so aus:

// 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");
}

Dies entspricht in etwa meinen Vorstellungen, aber ich möchte wirklich den öffentlichen Schlüssel des Signaturzertifikats verwenden, um zu überprüfen, ob die signierte Zieldatei tatsächlich mit meinem bestimmten öffentlichen / privaten Schlüsselpaar erstellt wurde.

Verwendung derCMSG_ENCRYPTED_DIGEST Diesen Code als erfolgreich markieren:

// 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);

Fazit Frage: Angesichts der von entdeckten ZertifikatinformationenCryptQueryObjectWelche Technik sollte ich verwenden, um sicherzustellen, dass die Zieldatei tatsächlich mit dem privaten Schlüssel signiert wurde, der dem öffentlichen Schlüssel entspricht, der mir zur Verfügung steht, wenn der obige Code ausgeführt wird?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage