C#从CA standalone获取证书

时间:2017-01-13 14:00:43

标签: c# certificate x509certificate

我有一个独立的CA,我需要使用C#按证书序列号搜索来获取完整的证书base64字符串。

已尝试使用X509Store,尝试使用CA名称,主机名\ ca-name以及所有StoreName和StoreLocation可能的变体

store = new X509Store("my-ca");
store.Open(OpenFlags.ReadOnly);
ret += "Count: " + store.Certificates.Count;
foreach (X509Certificate2 cert in store.Certificates)
{
    ret += "cert.SerialNumber: " + cert.SerialNumber;
}

并尝试使用CCertView / CCertRequest,此方法返回信息,但它不是完整的证书,当我从CA手动导出时字符串不相等。

public string GetCertificateBase64Original(string certificateSerialNumber)
{
    string certificateBase64 = string.Empty;

    try
    {
        CCertView certView = new CCertViewClass();
        certView.OpenConnection(this.nameCA);

        certView.SetResultColumnCount(2);

        int requestIDColumnIndex = certView.GetColumnIndex(0, "RequestID");
        int certificateSerialNumberColumnIndex = certView.GetColumnIndex(0, "SerialNumber");

        certView.SetResultColumn(requestIDColumnIndex);
        certView.SetResultColumn(certificateSerialNumberColumnIndex);

        object objSerialNumber = certificateSerialNumber;

        certView.SetRestriction(certificateSerialNumberColumnIndex, CVR_SEEK_EQ, CVR_SORT_NONE, ref objSerialNumber);

        IEnumCERTVIEWROW rowsEnum;
        rowsEnum = certView.OpenView();

        IEnumCERTVIEWCOLUMN objCol;
        rowsEnum.Reset();

        int requestID = 0;

        while (rowsEnum.Next() != -1)
        {
            objCol = rowsEnum.EnumCertViewColumn();

            while (objCol.Next() != -1)
            {
                if (objCol.GetName() == "RequestID")
                {
                    try
                    {
                        requestID = SafeConvert.ToInt(objCol.GetValue(PROPTYPE_STRING));
                    }
                    catch
                    {
                    }
                }
            }
        }

        if (requestID > 0)
        {
            CCertRequest certRequest = new CCertRequest();

            certRequest.GetIssuedCertificate(this.nameCA, requestID, certificateSerialNumber);

            certificateBase64 = SafeConvert.ToString(certRequest.GetFullResponseProperty(FR_PROP_FULLRESPONSE, 0, PROPTYPE_BINARY, CR_OUT_BASE64));
        }
    }
    catch
    {
    }

    return (certificateBase64);
}

根本没有成功。

2 个答案:

答案 0 :(得分:0)

问题是您正在请求包含完整响应的FR_PROP_FULLRESPONSE属性(IIRC,PKCS#7消息)。相反,您应该只请求颁发的证书属性:FR_PROP_ISSUEDCERTIFICATE

BTW ICertRequest接口调用不是必需的。为什么不将RawCertificate列放入ICertView接口调用中的结果列列表中,然后获取结果?

答案 1 :(得分:0)

使用此代码解决

https://blogs.msdn.microsoft.com/alejacma/2012/04/04/how-to-export-issued-certificates-from-a-ca-programatically-c/ https://blogs.msdn.microsoft.com/alejacma/2010/05/10/how-to-get-info-from-client-certificates-issued-by-a-ca-c/

public string GetCertificateBase64(string certificateSerialNumber)
{
    string certificateBase64 = string.Empty;

    try
    {
        // Variables
        CERTADMINLib.CCertView certView = null;
        CERTADMINLib.IEnumCERTVIEWROW certViewRow = null;
        CERTADMINLib.IEnumCERTVIEWCOLUMN certViewColumn = null;
        int iColumnCount = 0;
        object objValue = null;

        // Connecting to the Certificate Authority
        certView = new CERTADMINLib.CCertView();
        certView.OpenConnection(this.nameCA);

        // Get a column count and place columns into the view
        iColumnCount = certView.GetColumnCount(0);
        certView.SetResultColumnCount(iColumnCount);

        // Place each column in the view.
        for (int x = 0; x < iColumnCount; x++)
        {
            certView.SetResultColumn(x);
        }

        int certificateSerialNumberColumnIndex = certView.GetColumnIndex(0, "SerialNumber");
        object objSerialNumber = certificateSerialNumber;
        certView.SetRestriction(certificateSerialNumberColumnIndex, CVR_SEEK_EQ, CVR_SORT_NONE, ref objSerialNumber);

        // Open the View and reset the row position
        certViewRow = certView.OpenView();
        certViewRow.Reset();

        // Enumerate Row and Column Information

        // Rows (one per cert) 
        for (int x = 0; certViewRow.Next() != -1; x++)
        {
            // Columns with the info we need
            certViewColumn = certViewRow.EnumCertViewColumn();
            while (certViewColumn.Next() != -1)
            {
                switch (certViewColumn.GetDisplayName())
                {
                    // Binary Certificate
                    case "Binary Certificate":
                        objValue = certViewColumn.GetValue(CV_OUT_BASE64);
                        if (objValue != null)
                        {
                            certificateBase64 = objValue.ToString();
                        }
                        break;

                    default:
                        break;
                }
            }
        }
    }
    catch (Exception ex)
    {
        certificateBase64 += Environment.NewLine + "ex: " + ex.Message;
    }

    return certificateBase64;
}
相关问题