¿Cómo verificar que mi organización firmó un binario de Windows de confianza?

Esta es una pregunta de seguimiento parapregunta 1072540, 'WinVerifyTrust para verificar una firma específica?'.

Quiero escribir una función en C ++. Llamémosla.TrustedByUs de la forma:

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

La idea es que le demos a esta función una ruta a un archivo binario .dll o .exe que se haya firmado con una firma digital. lospathToPublicKey cadena es la ruta a una clave pública de nuestro certificado de firma particular.

Usando el código enhttp://support.microsoft.com/kb/323809 Es bastante sencillo verificar que lapathToBinary De hecho, el sistema operativo confía en el archivo.

Ahora que estoy en el mismo lugar que el escritor de la pregunta 1072540, sé que el sistema operativo confía en el firmante de este binario, pero quiero saber si la clave RSA de mi organización es la que firmó el binario.

El KB323809 muestra cómo extraer las cadenas del certificado incrustado en nuestro archivo binario. Este ejemplo muestra cómo extraer cadenas del certificado de firma en suGetProgAndPublisherInfo función, pero me siento incómodo al utilizar una coincidencia de cadena para verificar el certificado.

Lo que me gustaría hacer es extraer la clave pública de la firma incorporada y compararla con la clave pública que corresponde con la clave privada que firmó mi archivo binario en primer lugar.

La documentación paraCryptMsgGetParam dice que elCMSG_SIGNER_CERT_ID_PARAM parámetro 'Devuelve la información en un firmante del mensaje necesario para identificar la clave pública del firmante'. Logro obtener el número de serie del certificado con esta clave. Mi código se ve así:

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

Esto está cerca de lo que quiero, pero realmente me gustaría usar la clave pública del certificado de firma para verificar que el archivo binario firmado de destino fue creado con mi par de clave pública / privada particular.

Utilizando laCMSG_ENCRYPTED_DIGEST marcar este código tiene éxito:

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

Cuestión de fondo: Dada la información del certificado descubierta porCryptQueryObject, ¿qué técnica debo utilizar para garantizar que el archivo de destino se firmó de hecho con la clave privada que corresponde a la clave pública que está disponible para mí cuando se ejecuta el código anterior?

Respuestas a la pregunta(1)

Su respuesta a la pregunta