次の方法で共有


ドキュメントに証明書チェーンを埋め込む

このトピックでは、証明書チェーンを構成する証明書を XPS ドキュメントに埋め込む方法について説明します。 証明書チェーンは、ルート証明書を除くすべての証明書で構成され、end certificate によって識別されるサブジェクトを認定するために必要です。

XPS ドキュメントに証明書チェーンを埋め込むには、次のコード例に示すように、まず証明書チェーンを作成します。

コード例の CreateCertificateChain メソッドは、パラメーターとして certificateStore を受け入れます。これは HCERTSTORE 値です。 この値が NULL の場合、証明書はクライアント コンピューターの証明書サーバーから取得されます。 値が証明書ストアへのハンドルである場合、証明書は certificateStore によって参照されるそのストアから、およびクライアント コンピューターの証明書サーバーから取得されます。

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

次のコード例では、証明書から証明書チェーンを作成し、これらの証明書を XPS ドキュメントに追加します。 CertGetCertificateChain は、署名証明書が最初で、ルート証明書が最後である証明書チェーンを作成します。 この例では、署名証明書とルート証明書は追加されません。 署名証明書は、ドキュメントで最後に呼び出される署名メソッドである IXpsSignatureManager::Sign メソッドの呼び出しと共に追加されます。 ルート証明書は、署名の検証時にクライアント コンピューターの証明書サーバーによって提供される必要があるため、ドキュメントの署名時には追加されません。

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

次のステップ

ファイルから証明書を読み込む

証明書が署名メソッドをサポートしていることを確認する

システムでダイジェスト メソッドがサポートされていることを確認する

この例で使用

CERT_CONTEXT

CertGetCertificateChain

CRYPT_OID_INFO

IOpcCertificateSet

IXpsSigningOptions

詳細情報

Cryptography API

暗号化関数

デジタル証明書

証明書チェーン

証明書の信頼の検証

XPS デジタル署名 API のエラー

XPS ドキュメントのエラー

XML Paper Specification