Condividi tramite


Incorporare catene di certificati in un documento

In questo argomento viene descritto come incorporare i certificati che costituiscono una catena di certificati in un documento XPS. Una catena di certificati è costituita da tutti i certificati, ad eccezione del certificato radice, necessari per certificare l'oggetto identificato dal certificato finale.

Per incorporare una catena di certificati in un documento XPS, creare prima di tutto la catena di certificati come illustrato nell'esempio di codice seguente.

Il metodo CreateCertificateChain nell'esempio di codice accetta certificateStore come parametro, ovvero un valore HCERTSTORE . Se questo valore è NULL, i certificati verranno recuperati dal server certificati del computer client. Se il valore è l'handle di un archivio certificati, i certificati verranno recuperati da tale archivio a cui fa riferimento certificateStore e dal server di certificati del computer client.

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

Nell'esempio di codice seguente viene creata una catena di certificati dai certificati e quindi questi certificati vengono aggiunti a un documento XPS. Si noti che CertGetCertificateChain crea la catena di certificati in cui il certificato di firma è il primo e il certificato radice è l'ultimo. Il certificato di firma e il certificato radice non vengono aggiunti in questo esempio. I certificati di firma verranno aggiunti con una chiamata al metodo IXpsSignatureManager::Sign , che deve essere l'ultimo metodo di firma chiamato nel documento. Il certificato radice non viene aggiunto quando il documento è firmato, perché deve essere fornito dal server certificati del computer client quando la firma viene convalidata.

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

Passaggi successivi

Caricare un certificato da un file

Verificare che un certificato supporti un metodo signature

Verificare che il sistema supporti un metodo Digest

Usato in questo esempio

CERT_CONTEXT

CertGetCertificateChain

CRYPT_OID_INFO

IOpcCertificateSet

IXpsSigningOptions

Ulteriori informazioni

API di crittografia

Funzioni di crittografia

Certificati digitali

Catene di certificati

Verifica attendibilità certificato

Errori dell'API di firma digitale XPS

Errori del documento XPS

Specifica di carta XML