本主題描述如何將構成憑證鏈結的憑證內嵌至 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;
}
相關主題
-
後續步驟
-
從檔案 載入憑證
-
此範例中使用的
-
如需詳細資訊