How to request an smartcard logon cert programmatically (C#)

Hi all,

The other day I created this C# sample which shows how to request an smartcard logon cert to a CA. It is based on this other sample: How to create a certificate request with CertEnroll and .NET (C#).

 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();

            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();

            CX509ExtensionTemplateName objExtensionTemplate = new CX509ExtensionTemplateName();

            string strRequest;



            try

            {

                requestText.Text = "";



                // Get all available CSPs

                objCSPs.AddAvailableCsps();



                //  Provide key info

                objPrivateKey.ContainerName = "Alex";

                objPrivateKey.ProviderName = "eToken Base Cryptographic Provider";

                objPrivateKey.ProviderType = X509ProviderType.XCN_PROV_RSA_FULL;

                objPrivateKey.Length = 1024;

                objPrivateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;

                objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES; 

                objPrivateKey.MachineContext = false;

                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.4.1.311.20.2.2"); // OID for Smartcard logon

                objObjectIds.Add(objObjectId);

                objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);

                objPkcs10.X509Extensions.Add((CX509Extension)objX509ExtensionEnhancedKeyUsage);



                // Template Extension

                objExtensionTemplate.InitializeEncode("SmartcardLogon");

                objPkcs10.X509Extensions.Add((CX509Extension)objExtensionTemplate);



                //  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.

Regards,

 

Alex (Alejandro Campos Magencio)