Decrypt my World

Cryptography, Security, Debugging and more!

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

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

Rate This

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.

Cheers,

 

Alex (Alejandro Campos Magencio)

  • Hi Rizwan,

    It may be related to the user's profile not being loaded: blogs.msdn.com/.../rsacryptoserviceprovider-fails-when-used-with-asp-net.aspx

  • I'm facing all new type of issue which is getting logged into System Event when i'm hosting my code to one of the environment which is as follows.

    Description:

    Application popup: Security Warning : You are about to install a certificate from a certification authority (CA) claiming to represent:

    My CA Name

    Windows cannot validate that the certificate is actually from "My CA Name". You should confirm its origin by contacting "My CA Name". The following number will assist you in this process:

    Thumbprint (sha1):

    Warning:

    If you install this root certificate, Windows will automatically trust any certificate issued by this CA. Installing a certificate with an unconfirmed thumbprint is a security risk. If you click "Yes" you acknowledge this risk.

    Do you want to install this certificate?

    For more information, see Help and Support Center at go.microsoft.com/.../events.asp.

    Any idea?

    Please help me .

    Thanks

    Rizwan

  • My app  is hosted on IIS and on webpage i get waiting message and after some time it gives me session time out error(which is normal behaviour of any asp.net app),it seems that it displayes some popup window and that is hidden some where which is not visible to us.

    Thanks

    Rizwan

  • We have resolved this issue by installing CA root certificate into machine where my app is hosted under local trust store so that it works for all the account on that system.

    Thanks

    Rizwan

  • Hi Alex,  I have installed enterprise CA and also trying to request certificate as mentioned in your blog. while executing the code mentioned above I am getting the following error:

    "The submission failed: Denied by Policy Module 0x80094801, The request does not contain a certificate template extension or the CertificateTemplate request attribute."

    So I added the template in the code objPkcs10.InitializeFromPrivateKey( X509CertificateEnrollmentContext.ContextUser, objPrivateKey,  "") but now I am getting the following error: Provider could not perform the action since the  context was acquired as silent.

    Can you provide some help. We are not using MMC to request certificate but trying to generate programmatically.

  • Hi Ashish,

    Here you have a sample that requests a cert with a certificate template:

    blogs.msdn.com/.../how-to-request-an-smartcard-logon-cert-programmatically-c.aspx

  • Thanks Alex.. it worked.. so basically I added the following piece of code: CX509ExtensionTemplateName objExtensionTemplate = new CX509ExtensionTemplateName();

    objExtensionTemplate.InitializeEncode("User1");

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

    P.S Do you have some similar example to request user cert on behalf by enrollment agent

  • Hi Ashish,

    I'm glad it worked. And regarding the other example you comment, I do. If it is not in my blog, I don't have it. And as I don't work on this subject any longer and I discontinued this blog, I won't have it. If you need further help, please contact Microsoft Technical Support.

    Cheers

  • Because I've been trying to figure out how to add "Request Email Address", I thought I'd reply here. It actually goes in the subject. It wold be Subject = "E=my@email.com, CN=MyCN". Hopefully this helps someone else.

  • Hi Alex, I am trying to submit certificate request for on behalf of other user to CA on Window Server 2003. Code in C# is like:

    using CERTCLIENTLib;

    using XENROLLLib;

    private const string ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";

    private const string EmailCertOID = "1.3.6.1.5.5.7.3.4";

    private const int PROV_RSA_FULL = 1;

    private const int XECR_CMC = 3;

    private const int CR_IN_ENCODEANY = 0xff;

    CEnroll certEnroll = new CEnroll();

    certEnroll.ProviderName = ProviderName;

    certEnroll.addCertTypeToRequest(TemplateName);

    certEnroll.ProviderType = PROV_RSA_FULL;

    certEnroll.KeySpec = AT_KEYEXCHANGE;

    certEnroll.GenKeyFlags = CRYPT_EXPORTABLE;

    certEnroll.EnableSMIMECapabilities = 1;

    certEnroll.SignerCertificate = Convert.ToBase64String(EnrollmentAgentCertificate.GetRawCertData());

    certEnroll.addNameValuePairToSignature("RequesterName", DomainName + @"\" + UserName);

    string subjectCN = "CN=" + UserName;

    string certRequest = certEnroll.createRequest(XECR_CMC, subjectCN, EmailCertOID);

    CCertRequest objCertRequest = new CCertRequest();

    int iDisposition = objCertRequest.Submit(CR_IN_ENCODEANY | CR_IN_FORMATANY, certRequest, string.Empty, CAAddress);

    on objCertRequest.Submit() I am getting below error:

    "Unable to cast COM object of type CertClientLib.CCertRequestClass to interface type CertClientLib.ICertRequest3. This operation failed because the QueryInterface call on the COM component for the interface with IID'{AFC8F92B-33A2-4861-BF36-2933B7CD67B3}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002(E_NOINTERFACE))"

    What can be the issue ?

  • hi,

    i using windows vista ... i am getting exception  Unable to cast COM object of type CERTENROLLLib.CX509CertificateRequestPKcs10Class to interface type CERTENROLLLib.IX509CErtificateRequestPkcs10V2. - Interface not found exception...

    I found IX509CertificateRequestPkcs10V2 is not supported in vista... and tried  IX509CertificateRequestPkcs10 objPkcs10 = (IX509CertificateRequestPkcs10)Activator.CreateInstance(Type.GetTypeFromProgID("X509Enrollment.CX509CertificateRequestPkcs10"));

    still having exception..

  • Hi there,

    I can get the resulting client certificate request signed, but after successfully installing the signed certificate, it's missing the private key. Any ideas as to why this happens?

    My code is pretty much the same as the example, with the exception that I submit the request to the CA manually in base64 format, and the user is given the option to generate the private key under machine context, not just currentuser.

    Thanks.

    Ray

  • Hi there,

    I'm having a issue with the class CX509Enrollment when I execute my code in Windows Vista. The code below works very well in Windows 7 and I can generate a CSR signed with SHA256 but when I execute the same code in Windows Vista, is generated a CSR and a Digital Certificate self-signed. After this, is impossible to publish the digital certificate generated by CA.

                   String providerName = "SafeSign Standard Cryptographic Service Provider";

                   objCSP.InitializeFromName("SafeSign Standard Cryptographic Service Provider");

                   objCSPs.Add(objCSP);

                   String date = DateTime.Now.ToString("MMddHHmmss") + DateTime.Now.Millisecond.ToString();

                   objPrivateKey.ProviderName = providerName;

                   objPrivateKey.ContainerName = "SERASA-" + date;

                   objPrivateKey.Length = 2048;

                   objPrivateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE;

                   objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_SIGNING_FLAG|X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_KEY_AGREEMENT_FLAG;

                   objPrivateKey.MachineContext = false;

                   objPrivateKey.CspInformations = objCSPs;

                   objPrivateKey.Create();

                   objPkcs10.InitializeFromPrivateKey(X509CertificateEnrollmentContext.ContextUser, objPrivateKey, "");

                   CObjectId hashobj = new CObjectId();

                   hashobj.InitializeFromAlgorithmName(ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID, ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlags.AlgorithmFlagsNone, "SHA256");

                   objPkcs10.HashAlgorithm = hashobj;

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

                   );

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

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

                   objDN.Encode("CN=Eder Souza, O=e-Safer, OU=Consultoria, OU=ICP-Brasl", X500NameFlags.XCN_CERT_NAME_STR_NONE);

                   objPkcs10.Subject = objDN;

                   objEnroll.InitializeFromRequest(objPkcs10);

                   strRequest = objEnroll.CreateRequest(EncodingType.XCN_CRYPT_STRING_BASE64);

                   txtCSR.Text = strRequest;

    I will appreciate any help.

    Thank you.

    Eder

  • How to add a new property in ICertProperties. Can you please reply its very urgent.

    Thanks in advance.

  • In the link below there is a related code which works like a charm!!... I used this in a Windows Server 2008 R2 installation. Hope this help to others as an alternative to the code posted here :)

    http://sharetext.org/Xird

Page 6 of 7 (100 items) «34567
Leave a Comment
  • Please add 8 and 5 and type the answer here:
  • Post
Translate This Page