Überprüfen, ob ein Zertifikat eine Signaturmethode unterstützt

In diesem Thema wird beschrieben, wie Sie überprüfen, ob ein Zertifikat eine bestimmte Signaturmethode unterstützt.

Die CryptXmlEnumAlgorithmInfo in der Microsoft Crypto-API zählt die Eigenschaften eines Zertifikats auf und wird in diesem Codebeispiel verwendet, um die von dem Zertifikat unterstützten Signaturmethoden aufzuzählen. Um CryptXmlEnumAlgorithmInfo zum Aufzählen der vom Zertifikat unterstützten Signaturmethoden zu verwenden, muss der Aufrufer eine Rückrufmethode und eine Datenstruktur im Aufruf von CryptXmlEnumAlgorithmInfo bereitstellen, sodass Daten an die Rückrufmethode übergeben werden können.

Die im nächsten Codebeispiel verwendete Datenstruktur weist die folgenden Felder auf:

Feld Beschreibung
userSignatureAlgorithmToCheck Ein LPWSTR-Feld, das auf die Zeichenfolge verweist, die den URI des Signaturalgorithmus enthält, der überprüft werden soll.
certificateAlgorithmInfo Ein Zeiger auf eine CRYPT_OID_INFO-Struktur, die Informationen zu einem Signaturalgorithmus enthält, der vom Zertifikat unterstützt wird.
userSignatureAlgorithmSupported Ein boolescher Wert, der angibt, ob der Signaturalgorithmus vom Zertifikat unterstützt wird.

 

struct SignatureMethodData
{
    LPCWSTR             userSignatureAlgorithmToCheck; 
    PCCRYPT_OID_INFO    certificateAlgorithmInfo; 
    BOOL                userSignatureAlgorithmSupported; 
};

Die Crypto-API-Methode, die das Zertifikat überprüft, verwendet eine Rückrufmethode, um Daten an den Aufrufer zurückzugeben. CryptXmlEnumAlgorithmInfo zählt die vom Zertifikat unterstützten Signaturmethoden auf und ruft die Rückrufmethode für jede Signaturmethode auf, bis die Rückrufmethode FALSE zurückgibt, oder bis alle Signaturmethoden im Zertifikat aufgezählt wurden.

Die Rückrufmethode im nächsten Codebeispiel sucht nach einer von CryptXmlEnumAlgorithmInfo übergebenen Signaturmethode, die der von der aufrufenden Methode bereitgestellten Signaturmethode entspricht. Wenn eine Übereinstimmung gefunden wird, überprüft die Rückrufmethode, ob die Signaturmethode auch vom System unterstützt wird. Wenn die Signaturmethoden übereinstimmen und vom System unterstützt werden, wird die Signaturmethode als vom System unterstützt gekennzeichnet, und die Rückrufmethode gibt FALSE zurück.

BOOL WINAPI 
EnumSignatureMethodCallback (
    __in const CRYPT_XML_ALGORITHM_INFO *certMethodInfo,
    __inout_opt void *userArg
)
{
    // MAX_ALG_ID_LEN is used to set the maximum length of the 
    // algorithm URI in the string comparison. The URI is not 
    // likely to be longer than 128 characters so a fixed-size
    // buffer is used in this example.
    // To make this function more robust, you might consider
    // setting this value dynamically.
    static const size_t MAX_ALG_ID_LEN = 128;
    SignatureMethodData *certificateAlgorithmData = NULL;

    if (NULL != userArg) {
        // Assign user data to local data structure
        certificateAlgorithmData = (SignatureMethodData*)userArg;
    } else {
        // Unable to continue this enumeration 
        //   without data from calling method.
        return FALSE;
    }
    
    // For each algorithm in the enumeration, check to see if the URI 
    //  of the algorithm supported by the certificate matches the URI 
    //  of the algorithm being tested.
    int cmpResult = 0;
    cmpResult = wcsncmp( 
        certMethodInfo->wszAlgorithmURI, 
        certificateAlgorithmData->userSignatureAlgorithmToCheck, 
        MAX_ALG_ID_LEN );
    if ( 0 == cmpResult )
    {
        // This is a match...
        // Check to see if the algorithm supported by the 
        //  certificate matches any of the supported algorithms 
        //  on the system.
        cmpResult = wcsncmp(
            certMethodInfo->wszCNGExtraAlgid, 
            certificateAlgorithmData->certificateAlgorithmInfo->pwszCNGAlgid, 
            MAX_ALG_ID_LEN );
        if ( 0 == cmpResult )
        {
            // This is also a match so set the field in the data structure
            //   provided by the calling method.
            certificateAlgorithmData->userSignatureAlgorithmSupported = TRUE;
            // A match was found so there is no point in continuing 
            //  the enumeration.
            return FALSE;
        }
    }
    // The enumeration stops when the callback method returns FALSE. 
    //   If here, then return TRUE because a matching algorithm has
    //   not been found.
    return TRUE;
}

Im folgenden Codebeispiel wird die Überprüfungsfunktionalität von einer einzelnen Methode umschlossen. Diese Methode gibt einen booleschen Wert zurück, der angibt, ob das Zertifikat die Signaturmethode unterstützt und die Signaturmethode vom System unterstützt wird.

BOOL 
SupportsSignatureAlgorithm (
    __in LPCWSTR signingMethodToCheck,
    __in PCCERT_CONTEXT certificateToCheck
)
{
    HRESULT     hr = S_OK;

    // Initialize the structure that contains the   
    //  information about the signature algorithm to check
    SignatureMethodData        certificateAlgorithmData;

    certificateAlgorithmData.userSignatureAlgorithmSupported = 
        FALSE;
    certificateAlgorithmData.userSignatureAlgorithmToCheck = 
        signingMethodToCheck;

    // Call the crypt API to get information about the algorithms
    //   that are supported by the certificate and initialize 
    //   certificateAlgorithmData
    certificateAlgorithmData.certificateAlgorithmInfo = CryptFindOIDInfo (
        CRYPT_OID_INFO_OID_KEY,
        certificateToCheck->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId,
        CRYPT_PUBKEY_ALG_OID_GROUP_ID | CRYPT_OID_PREFER_CNG_ALGID_FLAG);

    if (certificateAlgorithmData.certificateAlgorithmInfo != NULL)
    {
        // Enumerate the algorithms that are supported by the 
        //   certificate, and use our callback method to determine if
        //   the user supplied signature algorithm is supported by 
        //     the certificate.
        //
        // Note that CRYPT_XML_GROUP_ID_SIGN is used to enumerate
        //  the signature methods
        hr = CryptXmlEnumAlgorithmInfo(
            CRYPT_XML_GROUP_ID_SIGN,  // NOTE: CRYPT_XML_GROUP_ID_SIGN
            CRYPT_XML_FLAG_DISABLE_EXTENSIONS,
            (void*)&certificateAlgorithmData,
            EnumSignatureMethodCallback);
        // when the enumeration has returned successfully, 
        //  certificateAlgorithmData.userSignatureAlgorithmSupported
        //  will be TRUE if the signing method is supported by
        //  the certificate
    }
    return certificateAlgorithmData.userSignatureAlgorithmSupported;
}

Nächste Schritte

Laden eines Zertifikats aus einer Datei

Überprüfen, ob das System eine Digestmethode unterstützt

Einbetten von Zertifikatketten in ein Dokument

In diesem Beispiel verwendet

CryptFindOIDInfo

CRYPT_OID_INFO

CryptXmlEnumAlgorithmInfo

Weitere Informationen

Kryptografie-API

Kryptografiefunktionen

XPS-Digitalsignatur-API-Fehler

XPS-Dokumentfehler

XML Paper Specification