Einbetten von Zertifikatketten in ein Dokument

In diesem Thema wird beschrieben, wie Sie die Zertifikate, aus denen eine Zertifikatkette besteht, in ein XPS-Dokument einbetten. Eine Zertifikatkette besteht aus allen Zertifikaten, mit Ausnahme des Stammzertifikats, die erforderlich sind, um den vom Endzertifikat identifizierten Antragsteller zu zertifizieren.

Um eine Zertifikatkette in ein XPS-Dokument einzubetten, erstellen Sie zuerst die Zertifikatkette, wie im folgenden Codebeispiel veranschaulicht.

Die CreateCertificateChain-Methode im Codebeispiel akzeptiert certificateStore als Parameter, bei dem es sich um einen HCERTSTORE-Wert handelt. Wenn dieser Wert NULL ist, werden die Zertifikate vom Zertifikatserver des Clientcomputers abgerufen. Wenn der Wert das Handle für einen Zertifikatspeicher ist, werden die Zertifikate aus diesem Speicher abgerufen, auf den von CertificateStore verwiesen wird, sowie vom Zertifikatserver des Clientcomputers.

HRESULT 
CreateCertificateChain (
    __in PCCERT_CONTEXT            certificate,
    __in HCERTSTORE                certificateStore,
    __out PCCERT_CHAIN_CONTEXT* certificateChain
)
{
    HRESULT  hr = S_OK;

    CERT_CHAIN_PARA certificateChainParameters = {0};

    certificateChainParameters.cbSize = sizeof(CERT_CHAIN_PARA);
    certificateChainParameters.RequestedUsage.dwType = USAGE_MATCH_TYPE_AND;

    // CertGetCertificateChain builds a certificate chain that starts 
    //  from the PCCERT_CONTEXT structure provided by the caller.
    //  After the certificate chain has been successfully created, 
    //  then the authenticity of the certificate can be determined 
    //  by examining the errors, if any, that occurred while the chain
    //  was created.
    BOOL successCreatingCertChain = CertGetCertificateChain (
        NULL,
        certificate,
        NULL,
        certificateStore,
        &certificateChainParameters,
        CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
        NULL,
        certificateChain);

    if (!successCreatingCertChain)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
    }
    return hr;
}

Im folgenden Codebeispiel wird eine Zertifikatkette aus Zertifikaten erstellt und dann diese Zertifikate einem XPS-Dokument hinzugefügt. Beachten Sie, dass CertGetCertificateChain die Zertifikatkette erstellt, in der das Signaturzertifikat zuerst und das Stammzertifikat zuletzt steht. Das Signaturzertifikat und das Stammzertifikat werden in diesem Beispiel nicht hinzugefügt. Die Signaturzertifikate werden mit einem Aufruf der IXpsSignatureManager::Sign-Methode hinzugefügt, welche die letzte Signaturmethode sein sollte, die für das Dokument aufgerufen wird. Das Stammzertifikat wird beim Signieren des Dokuments nicht hinzugefügt, da es vom Zertifikatserver des Clientcomputers bereitgestellt werden muss, wenn die Signatur überprüft wird.

HRESULT
EmbedCertificateChainInXpsPackage (
    __in IXpsSigningOptions *signingOptions,
    __in PCCERT_CONTEXT signingCertificate
)
{
    HRESULT                 hr                           = S_OK;
    PCCERT_CHAIN_CONTEXT    certificateChainContext      = NULL;
    IOpcCertificateSet      *certificateSetToUpdate      = NULL;
    DWORD                   certificateChainContextIndex = 0;

    // Create the entire certificate chain that originates 
    //  from the certificate that is used to sign the XPS document.
    hr = CreateCertificateChain(
        signingCertificate, 
        NULL, 
        &certificateChainContext);

    if (SUCCEEDED(hr))
    {
        // The signing options of an XPS document contain a pointer to 
        //  an IOpcCertificateSet interface that can be retrieved by 
        //  calling the GetCertificateSet method.
        hr = signingOptions->GetCertificateSet(&certificateSetToUpdate);
    }
    if (SUCCEEDED(hr))
    {
        // for each certificate chain context in this certificate...
        for (certificateChainContextIndex = 0; 
             certificateChainContextIndex < certificateChainContext->cChain; 
             certificateChainContextIndex++)
        {
            // inside a certificate chain context, 
            DWORD adjustedSimpleChainStartIndex = 0;
            DWORD adjustedSimpleChainEndIndex = 0;
            DWORD simpleCertChainIndex = 0;
            CERT_SIMPLE_CHAIN  *simpleCertificateChainWithinContext = NULL;

            // get the information about the certificate chain
            //  set the first item in the certificate chain to load
            //  Ignore the first PCCERT_CONTEXT in the first CERT_SIMPLE_CHAIN
            //  because this is the certificate that was used to build
            //  the chain and is already loaded in the document
            if (certificateChainContextIndex == 0)
            {
                adjustedSimpleChainStartIndex = 1;
            }
            else
            {
                adjustedSimpleChainStartIndex = 0;
            }
                    
            //  get the last item in the certificate chain
            simpleCertificateChainWithinContext = 
                certificateChainContext->rgpChain[certificateChainContextIndex];
            adjustedSimpleChainEndIndex = 
                simpleCertificateChainWithinContext->cElement;

            // Ignore the last PCCERT_CONTEXT in the last CERT_SIMPLE_CHAIN
            //  because this is the root certificate that must be retrieved
            //  from the client computer's certificate server.
            if (certificateChainContextIndex == certificateChainContext->cChain - 1)
            {
                if (adjustedSimpleChainEndIndex != 0)
                {
                    adjustedSimpleChainEndIndex = adjustedSimpleChainEndIndex - 1;
                }
            }

            // for each certificate chain in this context...
            for (simpleCertChainIndex = adjustedSimpleChainStartIndex; 
                 simpleCertChainIndex < adjustedSimpleChainEndIndex;
                 simpleCertChainIndex++)
            {
                // Add the certificate to the XPS document.
                PCCERT_CONTEXT certificateToEmbed = 
                    simpleCertificateChainWithinContext->rgpElement[simpleCertChainIndex]->pCertContext;
                if (FAILED(hr = certificateSetToUpdate->Add(certificateToEmbed)))
                {
                    break; // out of for loop with failed hr
                }
            }
        }
    }
    return hr;
}

Nächste Schritte

Laden eines Zertifikats aus einer Datei

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

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

In diesem Beispiel verwendet

CERT_CONTEXT

CertGetCertificateChain

CRYPT_OID_INFO

IOpcCertificateSet

IXpsSigningOptions

Weitere Informationen

Kryptografie-API

Kryptografiefunktionen

digitale Zertifikate

Zertifikatketten

Überprüfung der Zertifikatvertrauensstellung

API-Fehler bei der digitalen XPS-Signatur

XPS-Dokumentfehler

XML Paper Specification