我正在尝试编写申请申请证书并使用代码撤销证书。 通过引用msdn,我使用ICertRequest3接口实现了APPLICATION Certification部分,并使用ICertAdmin2 :: RevokeCertificate接口实现了Revoking部分。
问题是,它需要ICertAdmin2 :: RevokeCertificate证书的序列号才能开始工作,我不知道如何获取序列号属性 CA颁发的证书。
具体来说,我需要找到一种方法来在用ICertRequest3提交请求后提取CA颁发的证书的序列号属性。
有关您的信息,以下是申请和撤销证书的代码段。
HRESULT enrollWithICertRequest3(
X509CertificateEnrollmentContext context,
LPCWSTR template_name,
X509EnrollmentAuthFlags policy_server_authtype,
LPCWSTR policy_server_url,
LPCWSTR policy_server_username,
LPCWSTR policy_server_password,
X509EnrollmentAuthFlags enrollment_server_authtype,
LPCWSTR enrollment_server_url,
LPCWSTR enrollment_server_username,
LPCWSTR enrollment_server_password,
BSTR *cert_base64)
{
HRESULT hr = S_OK;
BSTR bstr_template_name = NULL;
BSTR bstr_policyserver_url = NULL;
BSTR bstr_policyserver_id = NULL;
BSTR bstr_policyserver_username = NULL;
BSTR bstr_policyserver_password = NULL;
IX509EnrollmentPolicyServer *policyserver_interface = NULL;
IX509CertificateTemplates *templates_interface = NULL;
IX509CertificateTemplate *template_interface = NULL;
IX509Enrollment2 *enroll2_interface = NULL;
BSTR bstrRequest = NULL;
BSTR bstrEnrollmentServerUrl = NULL;
BSTR bstrEnrollmentServerUsername = NULL;
BSTR bstrEnrollmentServerPassword = NULL;
ICertRequest3 *request3_interface = NULL;
LONG disposition = 0;
BSTR bstr_disposition = NULL;
VARIANT var_fullresponse;
VariantInit(&var_fullresponse);
var_fullresponse.vt = VT_BSTR;
var_fullresponse.bstrVal = NULL;
bstr_template_name = SysAllocString(template_name);
bstr_policyserver_url = SysAllocString(policy_server_url);
if(!bstr_template_name && template_name ||
!bstr_policyserver_url && policy_server_url)
{
hr = E_OUTOFMEMORY;
goto error;
}
if(policy_server_authtype == X509AuthUsername)
{
bstr_policyserver_username = SysAllocString(policy_server_username);
bstr_policyserver_password = SysAllocString(policy_server_password);
if(!bstr_policyserver_username && policy_server_username ||
!bstr_policyserver_password && policy_server_password)
{
hr = E_OUTOFMEMORY;
goto error;
}
}
else if(policy_server_authtype == X509AuthCertificate)
{
//This call is preparation of the call to pPolicyServer->SetCredential.
//For certificate authentication, bstrPolicyServerUsername should be a
//pointer to a memory blob in which certificate hash value is stored.
hr = hex2BstrByte(policy_server_username, &bstr_policyserver_username);
if(FAILED(hr))
goto error;
}
hr = CoCreateInstance(
__uuidof(CX509EnrollmentPolicyWebService),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509EnrollmentPolicyServer),
(void **)&policyserver_interface);
if(FAILED(hr))
goto error;
//The bstrPolicyServerId is optional
hr = policyserver_interface->Initialize(
bstr_policyserver_url, //[in] BSTR bstrPolicyServerUrl
NULL, //[in] BSTR bstrPolicyServerId
policy_server_authtype, //[in] X509EnrollmentAuthFlags authFlags
false, //[in] VARIANT_BOOL fIsUnTrusted
context); //[in] X509CertificateEnrollmentContext context
if(FAILED(hr))
goto error;
//This call sets authentication type and authentication credential
//to policy server to the object pointed by pPolicyServer.
//This call is necessary even for Kerberos authentication type.
hr = policyserver_interface->SetCredential(
NULL, //[in] LONG hWndParent
policy_server_authtype, //[in] X509EnrollmentAuthFlags flag
bstr_policyserver_username, //[in] BSTR strCredential
bstr_policyserver_password); //[in] BSTR strPassword
if(FAILED(hr))
goto error;
//The flag LoadOptionDefault means enrollment process reads
//policies (templates) from local cache in file system if it exists.
//Otherwise, it queries policies (templates) from policy server through
//http protocol, then caches them in local file system.
//The flag LoadOptionReload queries policies (templates) directly from
//policy server regardless of if cached policies (templates) exist.
hr = policyserver_interface->LoadPolicy(LoadOptionDefault); //[in] X509EnrollmentPolicyLoadOption option
if(FAILED(hr))
goto error;
//pTemplates points to collection of policies (templates)
hr = policyserver_interface->GetTemplates(&templates_interface);
if(FAILED(hr))
goto error;
//pTemplate points to the policy (template) specified by a template name
hr = templates_interface->get_ItemByName(bstr_template_name, &template_interface);
if(FAILED(hr))
goto error;
//This call is preparation of the call IX509Enrollment2::InstallResponse2
hr = policyserver_interface->GetPolicyServerId(&bstr_policyserver_id);
if(FAILED(hr))
goto error;
hr = CoCreateInstance(
__uuidof(CX509Enrollment),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IX509Enrollment2),
(void **) &enroll2_interface);
if(FAILED(hr))
goto error;
//This is a new API in Windows 7 to support http protocol
hr = enroll2_interface->InitializeFromTemplate(
context, //[in] X509CertificateEnrollmentContext context
policyserver_interface, //[in] IX509EnrollmentPolicyServer *pPolicyServer
template_interface); //[in] IX509CertificateTemplate *pTemplate
if(FAILED(hr))
goto error;
//Get request blob for the call ICertRequest3::Submit
hr = enroll2_interface->CreateRequest(
XCN_CRYPT_STRING_BASE64,
&bstrRequest);
if(FAILED(hr))
goto error;
hr = CoCreateInstance(
__uuidof(CCertRequest),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ICertRequest3),
(void **) &request3_interface);
if(FAILED(hr))
goto error;
bstrEnrollmentServerUrl = SysAllocString(enrollment_server_url);
if(!bstrEnrollmentServerUrl && enrollment_server_url)
{
hr = E_OUTOFMEMORY;
goto error;
}
if(enrollment_server_authtype == X509AuthUsername)
{
bstrEnrollmentServerUsername = SysAllocString(enrollment_server_username);
bstrEnrollmentServerPassword = SysAllocString(enrollment_server_password);
if(!bstrEnrollmentServerUsername && enrollment_server_username ||
!bstrEnrollmentServerPassword && enrollment_server_password)
{
hr = E_OUTOFMEMORY;
goto error;
}
}
else if(enrollment_server_authtype == X509AuthCertificate)
{
//This call is preparation of the call to pCertRequest3->SetCredential.
//For certificate authentication, bstrPolicyServerUsername should be a
//pointer to a memory blob in which certificate hash value is stored.
hr = hex2BstrByte(enrollment_server_username, &bstrEnrollmentServerUsername);
if(FAILED(hr))
goto error;
}
//This call sets authentication type and authentication credential
//to enrollment server to the object pointed by pCertRequest3.
//This call is necessary even for Kerberos authentication type.
hr = request3_interface->SetCredential(
NULL, //[in] LONG hWnd
enrollment_server_authtype, //[in] X509EnrollmentAuthFlags AuthType
bstrEnrollmentServerUsername, //[in] BSTR strCredential
bstrEnrollmentServerPassword); //[in] BSTR strPassword
if(FAILED(hr))
goto error;
//Submit request and get response
//For ICertRequest3::Submit, bstrConfig can be
//enrollment server URL
hr = request3_interface->Submit(
CR_IN_BASE64 | CR_IN_FORMATANY, //[in] LONG Flags
bstrRequest, //[in] BSTR const strRequest
NULL, //[in] BSTR const strAttributes
bstrEnrollmentServerUrl, //[in] BSTR const strConfig
&disposition); //[out, retval] LONG *pDisposition
if(FAILED(hr))
goto error;
//Check the submission status
if(disposition != CR_DISP_ISSUED) //Not enrolled
{
hr = request3_interface->GetDispositionMessage(&bstr_disposition);
if(FAILED(hr))
goto error;
request3_interface->GetLastStatus(&hr);
if(disposition == CR_DISP_UNDER_SUBMISSION) //Pending
{
wprintf(L"The submission is in pending status: %s \n", bstr_disposition);
goto error;
}
else //Failed
{
wprintf(L"The submission failed: %s \n", bstr_disposition);
goto error;
}
}
// Get the issued certificate
hr = request3_interface->GetCertificate(CR_OUT_BASE64, cert_base64);
if(FAILED(hr))
goto error;
////Get full response for installation
//hr = request3_interface->GetFullResponseProperty(
// FR_PROP_FULLRESPONSENOPKCS7, //[in] LONG PropId (FR_PROP_*)
// 0, //[in] LONG PropIndex
// PROPTYPE_BINARY, //[in] LONG PropType (PROPTYPE_*
// CR_OUT_BASE64, //[in] LONG Flags (CR_OUT_*)
// &var_fullresponse); //[out, retval] VARIANT *pvarPropertyValue
//if(FAILED(hr))
// goto error;
////Install the response
//hr = enroll2_interface->InstallResponse2(
// AllowNone, //[in] InstallResponseRestrictionFlags Restrictions
// var_fullresponse.bstrVal, //[in] BSTR strResponse
// XCN_CRYPT_STRING_BASE64, //[in] EnrodingType Encoding
// bstr_policyserver_password, //[in] BSTR strPassword
// bstr_policyserver_url, //[in] BSTR strEnrollmentPolicyServerUrl
// bstr_policyserver_id, //[in] BSTR strEnrollmentPolicyServerID
// PsfNone, //[in] PolicyServerUrlFlags EnrollmentPolicyServerFlags
// policy_server_authtype); //[in] X509EnrollmentAuthFlags authFlags
//if(FAILED(hr))
// goto error
/*BSTR pwd = SysAllocString(L"tOngbupan");
hr = enroll2_interface->CreatePFX(pwd, PFXExportEEOnly, XCN_CRYPT_STRING_BASE64, cert_base64);
SysFreeString(pwd);*/
error:
SysFreeString(bstr_template_name);
SysFreeString(bstr_policyserver_url);
SysFreeString(bstr_policyserver_id);
SysFreeString(bstr_policyserver_username);
SysFreeString(bstr_policyserver_password);
SysFreeString(bstr_disposition);
SysFreeString(bstrEnrollmentServerUrl);
SysFreeString(bstrEnrollmentServerPassword);
SysFreeString(bstrEnrollmentServerUsername);
SysFreeString(bstrRequest);
if(!var_fullresponse.bstrVal)
VariantClear(&var_fullresponse);
if(policyserver_interface)
policyserver_interface->Release();
if(templates_interface)
templates_interface->Release();
if(request3_interface)
request3_interface->Release();
if(template_interface)
template_interface->Release();
if(enroll2_interface)
enroll2_interface->Release();
return hr;
}
bool revokeUserCert(const wstring& cert_serial_num)
{
BSTR bstrSerial = NULL; // certificate serial number
HRESULT hr;
LONG nDisp;
ICertAdmin2* pCertAdmin = NULL;
bstrSerial = SysAllocString(cert_serial_num.c_str());
hr = CoCreateInstance(
CLSID_CCertAdmin,
NULL, // pUnkOuter
CLSCTX_INPROC_SERVER,
IID_ICertAdmin2,
(void **) &pCertAdmin);
if(FAILED(hr))
{
printf("init icertadmin error\n");
goto error;
}
ICertConfig* pCertConfig = NULL;
BSTR strCAConfig = NULL;
// Create ICertConfig
hr = CoCreateInstance(
__uuidof(CCertConfig),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(ICertConfig),
(void**)&pCertConfig);
// Get CA config
hr = pCertConfig->GetConfig(CC_FIRSTCONFIG, &strCAConfig);
if (FAILED(hr))
{
printf("Failed GetConfig [%x]\n", hr);
goto error;
}
hr = pCertAdmin->IsValidCertificate(strCAConfig, bstrSerial, &nDisp);
if (FAILED(hr))
{
printf("Failed IsValidCertificate [%x]\n", hr);
goto error;
}
if(nDisp != CA_DISP_VALID)
{
printf("givin certificate is not valid\n");
goto error;
}
// Revoke the certificate.
// pCertAdmin is a previously instantiated ICertAdmin object.
hr = pCertAdmin->RevokeCertificate( strCAConfig,
bstrSerial,
0,
0);
if (FAILED(hr))
{
/*_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();*/
//printf("Failed RevokeCertificate. [%x] [%s]\n", hr, ConvertWCSToMBS(errMsg, sizeof(errMsg)).c_str());
printf("Failed RevokeCertificate. [%x] \n", hr);
goto error;
}
else
printf("Certificate %ws revoked.\n", bstrSerial );
// Done processing.
error:
// Free resources.
if (bstrSerial)
SysFreeString( bstrSerial );
if(strCAConfig)
SysFreeString( strCAConfig );
if(pCertAdmin != NULL) { pCertAdmin->Release(); }
if(pCertConfig != NULL) { pCertConfig->Release(); }
return SUCCEEDED(hr);
}
答案 0 :(得分:0)
将已颁发的证书导入cert_base64字符串后,将其转换为字节数组,然后从字节数组中创建新的X509Certificate2对象。然后,您可以从X509Certificate2.SerialNumber属性访问序列号。在C#中,这将是:
X509Certificate2 x509cert = new X509Certificate2(getBytes(cert_base64));
string serialNumber = x509cert.SerialNumber;
private byte[] getBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}