请求密钥存档证书
以下示例演示如何创建和提交 证书请求 以及接收生成的密钥存档证书。 若要使此示例成功,必须将接收证书请求的 证书颁发机构 (CA) 配置为进行密钥存档。
以下步骤介绍如何创建和提交证书请求。
创建并提交证书请求
- 使用 ICertRequest2::GetCACertificate 方法检索 CA 的交换证书。
- 使用 ICEnroll4::P rivateKeyArchiveCertificate 属性指定检索到的 CA 交换证书是密钥存档证书。
- 使用 ICEnroll4::createRequest 方法创建 CMC 证书请求。
- 使用 ICertRequest2::Submit 方法将证书请求提交到 CA。 必须将 CA 配置为支持密钥存档。
以下步骤介绍如何检索颁发的证书以进行密钥存档。
检索颁发的证书以进行密钥存档
- 使用 ICertRequest2::GetFullResponseProperty 方法检索完整的响应,包括颁发的证书。
- 使用 ICEnroll4::acceptResponse 方法安装颁发的证书。
以下示例演示如何创建和提交证书请求以及接收生成的密钥存档证书。
// Pointer to interface objects.
ICEnroll4 * pEnroll = NULL;
ICertRequest2 * pRequest = NULL;
// BSTR variables.
BSTR bstrCACert = NULL;
BSTR bstrDN = NULL;
BSTR bstrCertAuth = NULL;
BSTR bstrReq = NULL;
BSTR bstrDispMsg = NULL;
BSTR bstrErrorMsg = NULL;
VARIANT varFullResp;
LONG lDisp =0;
LONG lRequestID = 0;
LONG lStatus = 0;
HRESULT hr;
// Initialize COM.
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
if ( FAILED( hr ) )
{
printf("Failed CoInitializeEx - [%x]\n", hr);
goto error;
}
// Create an instance of the Certificate Enrollment object.
hr = CoCreateInstance( CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICEnroll4,
(void **)&pEnroll);
if ( FAILED( hr ) )
{
printf("Failed CoCreateInstance - pEnroll [%x]\n", hr);
goto error;
}
// Create an instance of the Certificate Request object.
hr = CoCreateInstance( CLSID_CCertRequest,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICertRequest2,
(void **)&pRequest);
if ( FAILED( hr ) )
{
printf("Failed CoCreateInstance - pRequest [%x]\n", hr);
goto error;
}
// Allocate the BSTR that represents the certification authority.
// Note the use of '\\' to produce a single '\' in C++.
bstrCertAuth = SysAllocString(L"Server\\CertAuth");
if (NULL == bstrCertAuth)
{
printf("Failed SysAllocString\n");
goto error;
}
// Retrieve the CA's exchange certificate.
hr = pRequest->GetCACertificate(TRUE,
bstrCertAuth,
CR_OUT_BASE64HEADER,
&bstrCACert);
if (FAILED(hr))
{
printf("Failed GetCACertificate [%x]\n", hr);
goto error;
}
// Specify the retrieved certificate
// as the key archive certificate.
hr = pEnroll->put_PrivateKeyArchiveCertificate(bstrCACert);
if (FAILED(hr))
{
printf("put_PrivateKeyArchiveCertificate [%x]\n", hr);
goto error;
}
// Create the data for the request.
// A user interface or database retrieval could
// be used instead of this example's hard-coded text.
bstrDN = SysAllocString(L"CN=UserName" // common name
L",OU=UserUnit" // org unit
L",O=UserOrg" // org
L",L=UserCity" // locality
L",S=WA" // state
L",C=US"); // country/region
if (NULL == bstrDN)
{
printf("Failed SysAllocString\n");
goto error;
}
// Create the certificate request.
hr = pEnroll->createRequest( XECR_CMC,
bstrDN,
NULL,
&bstrReq );
if ( FAILED( hr ) )
{
printf("Failed createRequest - [%x]\n", hr);
goto error;
}
// Submit the certificate request.
hr = pRequest->Submit( CR_IN_CMC,
bstrReq,
NULL,
bstrCertAuth,
&lDisp );
if ( FAILED( hr ) )
{
printf("Failed Submit - [%x]\n", hr);
goto error;
}
// Evaluate the disposition of the submitted request.
switch (lDisp)
{
case CR_DISP_ISSUED:
printf("Certificate was issued.\n");
break;
case CR_DISP_ISSUED_OUT_OF_BAND:
case CR_DISP_INCOMPLETE:
case CR_DISP_ERROR:
case CR_DISP_DENIED:
case CR_DISP_UNDER_SUBMISSION:
case CR_DISP_REVOKED:
printf("Certificate was not issued: %d\n", lDisp);
break;
default:
printf("Unexpected disposition: %d\n", lDisp);
goto error;
}
// Retrieve the request ID.
hr = pRequest->GetRequestId(&lRequestID);
if ( FAILED(hr) )
{
printf("Failed GetRequestId - [%x]\n", hr);
goto error;
}
printf("The request ID is %d\n", lRequestID);
if (CR_DISP_ISSUED != lDisp)
{
// Provide information about why a certificate
// was not issued.
// Retrieve the last status.
hr = pRequest->GetLastStatus(&lStatus);
if ( FAILED(hr) )
{
printf("Failed GetLastStatus - [%x]\n", hr);
goto error;
}
// Retrieve the disposition message.
hr = pRequest->GetDispositionMessage(&bstrDispMsg);
if ( FAILED(hr) )
{
printf("Failed GetDispositionMessage - [%x]\n", hr);
goto error;
}
// Retrieve the error message.
hr = pRequest->GetErrorMessageText(lStatus,
CR_GEMT_HRESULT_STRING,
&bstrErrorMsg);
if ( FAILED(hr) )
{
printf("Failed GetErrorMessageText - [%x]\n", hr);
goto error;
}
// Display the information and exit.
printf("Request ID: %d\nDisposition: %S\nError: %S\n",
lRequestID,
bstrDispMsg,
bstrErrorMsg);
goto error;
}
// Retrieve the full response.
VariantInit(&varFullResp);
hr = pRequest->GetFullResponseProperty( FR_PROP_FULLRESPONSE,
0,
PROPTYPE_BINARY,
CR_OUT_BASE64,
&varFullResp );
if ( FAILED( hr ) )
{
printf("Failed GetFullResponseProperty - [%x]\n", hr);
goto error;
}
// Accept the response.
hr = pEnroll->acceptResponse(varFullResp.bstrVal);
if ( FAILED( hr ) )
{
printf("Failed AcceptResponse - [%x]\n", hr);
goto error;
}
else
{
printf("Successfully completed processing\n");
}
error:
// Done processing.
// Clean up object resources.
if ( NULL != pEnroll )
pEnroll->Release();
if ( NULL != pRequest )
pRequest->Release();
// Free BSTR variables.
if ( NULL != bstrCACert )
SysFreeString ( bstrCACert );
if ( NULL != bstrDN )
SysFreeString ( bstrDN );
if ( NULL != bstrCertAuth )
SysFreeString ( bstrCertAuth );
if ( NULL != bstrReq )
SysFreeString ( bstrReq );
if ( NULL != bstrDispMsg )
SysFreeString ( bstrDispMsg );
if ( NULL != bstrErrorMsg )
SysFreeString ( bstrErrorMsg );
// Clear VARIANTS.
VariantClear(&varFullResp);
// Free COM resources.
CoUninitialize();
return hr;