获取带代码的证书的序列号

时间:2014-03-07 10:32:59

标签: windows certificate windows-server-2008

我正在尝试编写申请申请证书并使用代码撤销证书。 通过引用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);
}

1 个答案:

答案 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;
    }