要求金鑰封存憑證
下列範例示範如何建立和提交 憑證要求 ,以及接收產生的金鑰封存憑證。 若要讓此範例成功,必須針對金鑰封存設定接收憑證要求的 憑證授權單位單位 (CA) 。
下列步驟說明如何建立和提交憑證要求。
建立和提交憑證要求
- 使用 ICertRequest2::GetCACertificate 方法擷取 CA 的交換憑證。
- 指定擷取的 CA 交換憑證是使用 ICEnroll4::P rivateKeyArchiveCertificate 屬性的金鑰封存憑證。
- 使用 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;