Внедрение цепочек сертификатов в документ
В этом разделе описывается внедрение сертификатов, составляющих цепочку сертификатов в документ 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;
}
См. также
-
Дальнейшие действия
-
Используется в этом примере
-
Дополнительные сведения