Friday, May 28, 2010

How to create a certificate request with CertEnroll and .NET (C#)

Hi all,

The following C# sample shows how to use CertEnroll COM component to create a certificate request, send the request to the CA, get the response from the CA, and install the new certificate in the machine:

(Note that this sample is a WinForms app with 3 buttons -createRequestButton, sendRequestButton, acceptPKCS7Button- and 2 textboxes -requestText & responseText-)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

//  Add the CertEnroll namespace
using CERTENROLLLib;
using CERTCLIENTLib;

namespace CATest
{
   public partial class Form1 : Form
   {
       private const int CC_DEFAULTCONFIG = 0;
       private const int CC_UIPICKCONFIG = 0x1;
       private const int CR_IN_BASE64 = 0x1;
       private const int CR_IN_FORMATANY = 0;
       private const int CR_IN_PKCS10 = 0x100;
       private const int CR_DISP_ISSUED = 0x3;
       private const int CR_DISP_UNDER_SUBMISSION = 0x5;
       private const int CR_OUT_BASE64 = 0x1;
       private const int CR_OUT_CHAIN = 0x100;

       public Form1()
       {
           InitializeComponent();
       }

       // Create request
       private void createRequestButton_Click(object sender, EventArgs e)
       {
           //  Create all the objects that will be required
           CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10Class();
           CX509PrivateKey objPrivateKey = new CX509PrivateKeyClass();
           CCspInformation objCSP = new CCspInformationClass();
           CCspInformations objCSPs = new CCspInformationsClass();
           CX500DistinguishedName objDN = new CX500DistinguishedNameClass();
           CX509Enrollment objEnroll = new CX509EnrollmentClass();
           CObjectIds objObjectIds = new CObjectIdsClass();
           CObjectId objObjectId = new CObjectIdClass();
           CX509ExtensionKeyUsage objExtensionKeyUsage = new CX509ExtensionKeyUsageClass();
           CX509ExtensionEnhancedKeyUsage objX509ExtensionEnhancedKeyUsage = new CX509ExtensionEnhancedKeyUsageClass();
           string strRequest;

           try
           {
               requestText.Text = "";

               //  Initialize the csp object using the desired Cryptograhic Service Provider (CSP)
               objCSP.InitializeFromName(
                   "Microsoft Enhanced Cryptographic Provider v1.0"
               );

               //  Add this CSP object to the CSP collection object
               objCSPs.Add(
                   objCSP
               );

               //  Provide key container name, key length and key spec to the private key object
               //objPrivateKey.ContainerName = "AlejaCMa";
               objPrivateKey.Length = 1024;
               objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;
               objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;
               objPrivateKey.MachineContext = false;

               //  Provide the CSP collection object (in this case containing only 1 CSP object)
               //  to the private key object
               objPrivateKey.CspInformations = objCSPs;

               //  Create the actual key pair
               objPrivateKey.Create();

               //  Initialize the PKCS#10 certificate request object based on the private key.
               //  Using the context, indicate that this is a user certificate request and don't
               //  provide a template name
               objPkcs10.InitializeFromPrivateKey(
                   X509CertificateEnrollmentContext.ContextUser,
                   objPrivateKey,
                   ""
               );

               // Key Usage Extension
               objExtensionKeyUsage.InitializeEncode(
                   X509KeyUsageFlags.XCN_CERT_DIGITAL_SIGNATURE_KEY_USAGE |
                   X509KeyUsageFlags.XCN_CERT_NON_REPUDIATION_KEY_USAGE |
                   X509KeyUsageFlags.XCN_CERT_KEY_ENCIPHERMENT_KEY_USAGE |
                   X509KeyUsageFlags.XCN_CERT_DATA_ENCIPHERMENT_KEY_USAGE
               );
               objPkcs10.X509Extensions.Add((CX509Extension)objExtensionKeyUsage);

               // Enhanced Key Usage Extension
               objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2"); // OID for Client Authentication usage
               objObjectIds.Add(objObjectId);
               objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
               objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);

               //  Encode the name in using the Distinguished Name object
               objDN.Encode(
                   "CN=AlejaCMa",
                   X500NameFlags.XCN_CERT_NAME_STR_NONE
               );

               //  Assing the subject name by using the Distinguished Name object initialized above
               objPkcs10.Subject = objDN;

               // Create enrollment request
               objEnroll.InitializeFromRequest(objPkcs10);
               strRequest = objEnroll.CreateRequest(
                   EncodingType.XCN_CRYPT_STRING_BASE64
               );

               requestText.Text = strRequest;

           } catch (Exception ex)
           {
               MessageBox.Show(ex.Message);
           }
       }

       // Submit request to CA and get response
       private void sendRequestButton_Click(object sender, EventArgs e)
       {
           //  Create all the objects that will be required
           CCertConfig objCertConfig = new CCertConfigClass();
           CCertRequest objCertRequest = new CCertRequestClass();
           string strCAConfig;
           string strRequest;
           int iDisposition;
           string strDisposition;
           string strCert;

           try
           {
               strRequest = requestText.Text;

               // Get CA config from UI
               //strCAConfig = objCertConfig.GetConfig(CC_DEFAULTCONFIG);
               strCAConfig = objCertConfig.GetConfig(CC_UIPICKCONFIG);                

               // Submit the request
               iDisposition = objCertRequest.Submit(
                   CR_IN_BASE64 | CR_IN_FORMATANY,
                   strRequest,
                   null,
                   strCAConfig
               );

               // Check the submission status
               if (CR_DISP_ISSUED != iDisposition) // Not enrolled
               {
                   strDisposition = objCertRequest.GetDispositionMessage();

                   if (CR_DISP_UNDER_SUBMISSION == iDisposition) // Pending
                   {
                       MessageBox.Show("The submission is pending: " + strDisposition);
                       return;
                   }
                   else // Failed
                   {
                       MessageBox.Show("The submission failed: " + strDisposition);
                       MessageBox.Show("Last status: " + objCertRequest.GetLastStatus().ToString());
                       return;
                   }
               }

               // Get the certificate
               strCert = objCertRequest.GetCertificate(
                   CR_OUT_BASE64 | CR_OUT_CHAIN
               );

               responseText.Text = strCert;
           }
           catch (Exception ex)
           {
               MessageBox.Show(ex.Message);
           }
       }

       // Install response from CA
       private void acceptPKCS7Button_Click(object sender, EventArgs e)
       {
           //  Create all the objects that will be required
           CX509Enrollment objEnroll = new CX509EnrollmentClass();
           string strCert;
           
           try
           {
               strCert = responseText.Text;

               // Install the certificate
               objEnroll.Initialize(X509CertificateEnrollmentContext.ContextUser);
               objEnroll.InstallResponse(
                   InstallResponseRestrictionFlags.AllowUntrustedRoot,
                   strCert,
                   EncodingType.XCN_CRYPT_STRING_BASE64,
                   null
               );

               MessageBox.Show("Certificate installed!");
           }
           catch (Exception ex)
           {
               MessageBox.Show(ex.Message);
           }
       }      
   }
}

I hope this helps.

Read more: Decrypt my World

Posted via email from jasper22's posterous