Working with a Certificate Authority in C#


First of all I would like to apologize for the long delay between posts.  The holidays, a new baby, and work schedule had me running around quite a bit.  Anyway I'm back blogging and one of my new years resolutions was to keep doing brain dumps here in the hopes that it would help me lose the 20 pounds of sympathy weight that I gained during my wife's pregnancy. 


This month I wanted to cover something that I worked on some time ago because I dont see a lot of information elsewhere on how to work with a CA programmatically.  This is probably because a lot of people dont really need to do this, and CertUtil is a great command-line utility that has a ton of features.  However there may be a case or two where you want to write something yourself.  In the code below I will try to explain the basics of working with a Certificate Authority database. 


The key to connecting to the Certificate Authority is the ICertView interface (http://msdn2.microsoft.com/en-us/library/aa385414(VS.85).aspx).  Through this interface you can get all the information you need from the CA.  To get a reference to ICertView you will need to include a reference to Certadm.dll.  This dll is present on server versions Windows 2000 and later.


Step 1:  Connecting to the Certificate Authority


Connecting to the CA is fairly simple.  Just create an instance of CCertView and use OpenConnection();


CERTADMINLib.CCertView CView = new CERTADMINLib.CCertViewClass();


CView.OpenConnection(server + "\\" + ca);


 



I would like to note that the ca parameter is the name of  your CA that you specified when you installed Certificate Services.


Step 2:  Get a column count and place columns into the view


int iColumnCount = 0;


iColumnCount = CView.GetColumnCount(0);


CView.SetResultColumnCount(iColumnCount);


                                                                       


// Place each column in the view.


for (int x = 0; x < iColumnCount; x++)


{


      CView.SetResultColumn(x);


}



 


Step 3:  Open the View and reset the row position


 


//Open the View


CERTADMINLib.IEnumCERTVIEWROW rowsEnum;


rowsEnum = CView.OpenView();


                                                                             


CERTADMINLib.IEnumCERTVIEWCOLUMN objCol;


rowsEnum.Reset();



 


Step 4:  Enumerate Row and Column Information


There are too many columns to list here, but you should get the picture.  Pay attention to the PROPTYPE of the data that you want to retrieve.   Here are some constants you will need in your application:


public const int CV_OUT_BASE64 = 0x1;


public const int CV_OUT_BINARY = 0x2;


public const int CV_OUT_HEX = 0x4;


public const int CV_OUT_HEXASCII = 0x5;


public const int PROPTYPE_LONG = 0x1;


public const int PROPTYPE_DATE = 0x2;


public const int PROPTYPE_BINARY = 0x3;


public const int PROPTYPE_STRING = 0x4;


public const int PROPTYPE_MASK = 0xFF;


 


//Enumerate Rows                                                       


while (rowsEnum.Next() != -1)


{


      Certificate cert = new Certificate();


      objCol = rowsEnum.EnumCertViewColumn();


                             


      //Enumerate Columns                            


      while (objCol.Next() != -1)


      {


            switch (objCol.GetDisplayName())


            {


                  case "Request Disposition Message":


                        try


                        {


                          cert.DispMessage = objCol.GetValue(PROPTYPE_STRING).ToString();


                        }


                        catch


                        {


                              //Exception Handling


                        }


                        break;


                  case "Certificate Expiration Date":


                        try


                        {


                          cert.ExpirationDate = objCol.GetValue(PROPTYPE_DATE).ToString();


                        }


                        catch


                        {


                              //Exception Handling


                        }


         break;


                  default: 


                        break;


            }


      }


}


 


That's about it.  You can now add logic to work with your certificates.  Additional name properties are located here (http://msdn2.microsoft.com/en-us/library/aa386991(VS.85).aspx).  Happy coding.


 

Comments (7)
  1. secmaker says:

    Thanks, very good article but I’ve a problem.

    I can’t use the Certificate namespace (VS2008 can’t find directive or assembly).

    So, how do I import the Certificate namespace?

    Thanks again.

  2. JAtkins says:

    Thanks for the question, and sorry for the confusion.  I should have used a different name rather than certificate in the posting.  Certificate is just an object that I created to store the certificate properties retrieved from the CA.  

    Example:

    public class Certificate

    {

       private string requestId;

       public string RequestId

       {

           get { return requestId; }

           set { requestId = value; }

       }

       private string requesterName;

       public string RequesterName

       {

           get { return requesterName; }

           set { requestId = value; }

       }

       etc…..

    }

  3. secmaker says:

    Oh then I get it,

    I finally got this worked.

    Thanks again for good explanation.

  4. secmaker says:

    Hi again, an additional question:

    Do you know how to save the result to i.e. a ASP.NET Repeater, GridView or something like that?

    I can’t do this because the rows is created before the columns (?) and I don’t know how to workaround this.

    Du you have any suggestion about this?

    Thanks a lot.

  5. srecosta says:

    Nice post! It helped me a lot!

    Using this I was able to retrieve a certificate directly from CA using only its serial number.

    Thanks again.

  6. sambeauvois says:

    Thanks a lot for this post

    You give me a starting point ! I didn’t find any doc for what I wanted to do with the CA before viewing your article

  7. Don't forget that you need to release these com objects. Otherwise you will run out of connections with the CA. You should release the row object once for every assignment:

    rowsEnum = CView.OpenView();

    You should release the View object once for every call:

    CView.OpenConnection(server + "\" + ca);

    And you should release the column object once for every assignment:

    objCol = rowsEnum.EnumCertViewColumn();

Comments are closed.

Skip to main content