在檔中內嵌憑證鏈結
本主題描述如何將構成憑證鏈結的憑證內嵌至 XPS 檔。 憑證鏈結包含所有憑證,但根憑證除外,這些憑證需要認證結束憑證所識別的主體。
若要將憑證鏈結內嵌至 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;
}
相關主題
-
後續步驟
-
在此範例中使用
-
詳細資訊