Menyematkan Rantai Sertifikat dalam Dokumen

Topik ini menjelaskan cara menyematkan sertifikat yang membentuk rantai sertifikat ke dalam dokumen XPS. Rantai sertifikat terdiri dari semua sertifikat, kecuali sertifikat akar, yang diperlukan untuk mensertifikasi subjek yang diidentifikasi oleh sertifikat akhir.

Untuk menyematkan rantai sertifikat ke dalam dokumen XPS, pertama-tama buat rantai sertifikat seperti yang diilustrasikan dalam contoh kode berikut.

Metode CreateCertificateChain dalam contoh kode menerima certificateStore sebagai parameter, yang merupakan nilai HCERTSTORE . Jika nilai ini NULL, sertifikat akan diambil dari server sertifikat komputer klien. Jika nilainya adalah handel ke penyimpanan sertifikat, sertifikat akan diambil dari penyimpanan yang dirujuk oleh certificateStore serta dari server sertifikat komputer klien.

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;
}

Contoh kode berikut membuat rantai sertifikat dari sertifikat lalu menambahkan sertifikat ini ke dokumen XPS. Perhatikan bahwa CertGetCertificateChain membuat rantai sertifikat di mana sertifikat penandatanganan adalah yang pertama dan sertifikat akar terakhir. Sertifikat penandatanganan dan sertifikat akar tidak ditambahkan dalam contoh ini. Sertifikat penandatanganan akan ditambahkan dengan panggilan ke metode IXpsSignatureManager::Sign , yang seharusnya menjadi metode tanda tangan terakhir yang dipanggil pada dokumen. Sertifikat akar tidak ditambahkan ketika dokumen ditandatangani, karena harus disediakan oleh server sertifikat komputer klien ketika tanda tangan divalidasi.

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;
}

Langkah berikutnya

Memuat Sertifikat dari File

Verifikasi bahwa Sertifikat Mendukung Metode Tanda Tangan

Memverifikasi Sistem Mendukung Metode Hash

Digunakan dalam Contoh Ini

CERT_CONTEXT

CertGetCertificateChain

CRYPT_OID_INFO

IOpcCertificateSet

IXpsSigningOptions

Untuk Informasi Selengkapnya

API Kriptografi

Fungsi Kriptografi

Sertifikat Digital

Rantai Sertifikat

Verifikasi Kepercayaan Sertifikat

Kesalahan XPS Digital Signature API

Kesalahan Dokumen XPS

Spesifikasi Kertas XML