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.

Cheers,

 

Alex (Alejandro Campos Magencio)

Comments

  • Anonymous
    September 07, 2008
    Very good article, it helps me a lot :-)

  • Anonymous
    September 16, 2008
    I got the error:"The submission failed: Denied by Policy Module 0x80094801, The request does not contain a certificate template extension or the CertificateTemplate request attribute."How can I specify a certificate template extension?

  • Anonymous
    October 02, 2008
    http://support.microsoft.com/kb/910249

  • Anonymous
    November 12, 2008
    Hi,can you explain a little how to do the same with the "on behalf" feature ?I imagine, you need to sign the request before submiting ? how ?thksAnthony

  • Anonymous
    November 17, 2008
    HelloThank you for your sample codeBut I got an Errorusing CERTENROLLLib;using CERTCLIENTLib;the above using **** has error..Dose it must add some reference in this project?thank you very much

  • Anonymous
    November 18, 2008
    Yes, you have to add references to the CertEnroll & CertCli COM objects (Project > Add Reference > COM).

  • Anonymous
    November 19, 2008
    how does one compile this code?csc /t:library /r:cercli.dll does not work. Thanks.

  • Anonymous
    November 19, 2008
    Henok, take into account this is just a sample, and it's just a file of a complete project. This is part of a form part of a very basic WinForms project created with VS2008.

  • Anonymous
    November 23, 2008
    While trying to run the given example I am getting the error : CCertRequest::Submit: The RPC server is unavailable. 0x800706ba (WIN32: 1722).I am using Vista Ultimate as the client to run this application and submitting request to Standalone CA hosted on W2003 Enterprise edition server with Service Pack 2 and Hotfix for CA services for supporting Vista and 2008 Clients . This server is not part of any domain server. Just connceted to my companies intranet.I am able to get the certificate from this Vista machine through web enrollment module.I have checked that CA server and RPC server are running.Please give any pointer to what could be the problem.Thanks in advance.Rajendra

  • Anonymous
    January 14, 2009
    Thanks for the code, it is rare to find a similar one.I have 2 questions:If I have already a public key, how do I add it to the request.How to specify the CA to which I wil submit the request. Thanks in advance

  • Anonymous
    February 17, 2009
    The comment has been removed

  • Anonymous
    February 17, 2009
    The comment has been removed

  • Anonymous
    June 03, 2009
    How I can specify CA?when I putstrCAConfig = "somecertserver.com/certserver" (Windows 2003 CA Authority) getting{"CCertRequest::Submit: The RPC server is unavailable. 0x800706ba (WIN32: 1722)"}

  • Anonymous
    June 03, 2009
    Check the following MSDN article for details on how to specify a CA in the strCAConfig variable:ICertRequest2::Submit Methodhttp://msdn.microsoft.com/en-us/library/aa385054(VS.85).aspx"strConfig [in]Represents a valid configuration string for the Certificate Services server in the form COMPUTERNAMECANAME, where COMPUTERNAME is the server's network name, and CANAME is the common name of the certification authority, as entered during Certificate Services setup. For information about the configuration string name, see ICertConfig."I hope this helps.Regards,Alex

  • Anonymous
    June 05, 2009
    finally get the certificate!!! How would I create pfx file out of it.Here are my steps (according to your post):objEnroll.InitializeobjEnroll.InstallResponse objEnroll.CreatePFX which return me a string How I can create pfx file?

  • Anonymous
    June 05, 2009
    Figured it out:string ress = objEnroll.CreatePFX(password, PFXExportOptions.PFXExportEEOnly,                                                  EncodingType.XCN_CRYPT_STRING_BASE64);var fs = new FileStream(exportPath, FileMode.Create);               fs.Write(Convert.FromBase64String(ress), 0, Convert.FromBase64String(ress).Length);               fs.Close();

  • Anonymous
    June 10, 2009
    Is there a way to get pfx blob without installing response to local certificate store?Something like:objEnroll.Initialize something i am not aware of :-( objEnroll.CreatePFX which return me a string

  • Anonymous
    June 11, 2009
    Don't know a way. Don't think it's possible, because when we make a request, a partial cert with public/private key pair gets created in the profile of the user/machine. Then we send the request to the CA and its response gets combined to that partial cert to create the definite signed cert. That process requires the cert to be in the profile. You may get the PFX and delete the cert afterwards...

  • Anonymous
    June 12, 2009
    Thanks for explanation! I will go with a way you suggested.

  • Anonymous
    June 25, 2009
    Is it possible to emulate the function "Automatically Enroll Certificates" using CAPICOM or CertEnroll on XP to force auto enrollment ?Via MMC-Certificates - right-click on cert store - All Tasks - Automatically Enroll CertificatesThanks - Mike

  • Anonymous
    July 23, 2009
    Hi!Can you suggest some links or some code snippets for enrollment certificate for template "SmartcardLogon"? What should I change in your code to enroll certificate for smartcard?Thanks

  • Anonymous
    July 29, 2009
    I was wondering if there was ever a response to a question above because I have the same question but I can't find an answer.I have 2 questions:If I have already a public key, how do I add it to the request. (need this answer)How to specify the CA to which I wil submit the request. (don't need this answer) Thanks in advance

  • Anonymous
    August 10, 2009
    I create my own web site to request a certificate.  Everything works fine and I'm able to get the certificate from the CA into a string (strCert).Now, I need to send it to the user via the browser and install it on the user's PC.  I work with C# (VS2008) and .NET 3.5 inside a Web Application.Any thoughts?

  • Anonymous
    December 01, 2009
    Hello,I also have the exact same situation as Rene. I have written the code on windows server 2008 using asp.net C# to request for certificate. As if I call it from the client machine (another machin within LAN using http://ipaddress/ApplicationName) it works fine. But installResponse only installs it on the server machine. How can I send the certificate response to the Client machine so that it can install it within both IE and Firefox? Please help.Thank you in advance.

  • Anonymous
    January 15, 2010
    Is this solution good for the site that's hosted on Win2003 server?What would be the equivalent CertEnroll.dll COM in 2003?

  • Anonymous
    January 30, 2010
    Thanks for this sample!When I tried to initialize the IX509Enrollment object from template (InitializeFromTemplateName) - it failed when the minimum supported CA of the template was Windows Server 2008. It worked fine with the same template which its minimum supported CA is Windows Server 2003. (My CA is on Windows Server 2008x64, the code was invoked on the same computer).It fails in the CreateRequest stage, with the following exception:CertEnroll::CX509Enrollment::p_CreateRequest: Key does not exist. 0x8009000d (-2146893811)Any idea?Thanks,D.

  • Anonymous
    April 28, 2010
    hiI had a problem with the InitializeFromTemplateName method.I used it with succes in dev environment, but when I moved my application in stagin environment, it failed with the error :"CertEnroll::CX509CertificateRequestPkcs10::InitializeFromTemplateName: The requested certificate template is not supported by this CA. 0×80094800 (-2146875392)"So I tried to change the security but it wasn't the error sourcein fact, InitializeFromTemplateName can take the certificate template object identifier as parameterSo I used it and it workedI described that here :http://www.sambeauvois.be/blog/2010/04/the-ix509certificaterequestpkcs10-initializefromtemplatename-adventure/

  • Anonymous
    June 24, 2010
    The InitializeFromTemplateName method does work. Make sure you are using the template name opposed to it's display name, if you have spaces in the name, you are using the display name!! :)

  • Anonymous
    October 26, 2010
    Hi,I'm programing an application that request a certificate from Microsoft Enterprise CA on behalf users. Actually, I can request a certificate (with Certenroll) by using a template. the application is hosted on IIS on the enterprise CA server. But the certificate I request belong to the computer account. My problem is that I don't know request a certificate for a specific user on AD. I have no idea how to map my certificate request to a user! Do you (or anyone) know how? with attribute or methods i should add to your code to do so?Thanks,

  • Anonymous
    October 26, 2010
    Hi Jawcontact,If I understood correctly, you are using server side code to request certificates on behalf of users. If so, the typical solution is to create a PFX file in server side, and send it to user afterwards. So you could implement a solution like the following:Have server code to request and install the certificate in a  machine certificate store.The server will export the certificate + private key in PFX format from that cert store, and save it to some database or folder. User downloads the PFX file to local machine. Client side code installs the PFX certificate in the user’s certificate store. Regards,Alex

  • Anonymous
    October 28, 2010
    Hi Alejacma,Actually we would use a server side to request certificate on behalf users but my web application cannot. Here is the code that I use to request a certificat:       private const int CR_IN_BASE64 = 0x1;       private const int CR_IN_FORMATANY = 0;       private const string CertificateAuthorityAddress = "localhost\PKI Test Entreprise Issuing CA";       private const string distinguishedName = "CN=User Name1,OU=client1,DC=myDomain";           //  Create all the objects that will be required           CX509CertificateRequestPkcs10 objPkcs10 = new CX509CertificateRequestPkcs10Class();                   CX500DistinguishedName objDN = new CX500DistinguishedNameClass();           CX509Enrollment objEnroll = new CX509EnrollmentClass();           string strRequest;           objDN.Encode(               distinguishedName,               X500NameFlags.XCN_CERT_NAME_STR_NONE           );           objPkcs10.InitializeFromTemplateName(X509CertificateEnrollmentContext.ContextUser, "PKITUser");           // 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           );           sendRequest(strRequest);       // Submit request to CA and get response         private void sendRequest(string strRequest)       {           //  Create all the objects that will be required           CCertConfig objCertConfig = new CCertConfigClass();           CCertRequest objCertRequest = new CCertRequestClass();           string strCAConfig;           int iDisposition;           string strDisposition;           string strCert;           // Submit the request           iDisposition = objCertRequest.Submit(               CR_IN_BASE64 | CR_IN_FORMATANY,               strRequest,               null,               CertificateAuthorityAddress           );The problem is in the CA even if I've specified the user's Distinguish Name, the certificate that is issued belong to the local computer instead to belong to the user (in this exemple User Name1). How can I request a certificate for User Name1 and be stored in the ldap for this user and not for the computer account?

  • Anonymous
    July 15, 2011
    The exemple ist good. I  need to find an example of creating a certificate on-behalf-off, one where a different CSP is used (a smartcard csp) and the private key is stored on the card. I've run into a dead end with the enrollEOBOCMC example from the SDK because there is no way to influnce the private key object using the IX509CertificateRequestCmc interface. I tried GetInnerRequest, but that doesn't work.Thanks in advanceRobert

  • Anonymous
    August 22, 2011
    The comment has been removed

  • Anonymous
    September 19, 2011
    Hi Alejandro,Do you know how to do a PKCS #10 in client side with mozilla firefox compatible?Thanks in advance, Pablo

  • Anonymous
    October 04, 2011
    I am able create and publish the certificate request to my CA. I am also able to pull the certificate after it is created. But where is the certificate being installed? I cannot find it anywhere in the certificates MMC snap-in.

  • Anonymous
    October 09, 2011
    This code produces CSRs that after installing the certificate do not allow SSL 3.0, TLS 1.1 or 1.2 to work.When generating the CSR through the IIS7 manager SSL 3.0, TLS 1.1 and 1.2 work.

  • Anonymous
    October 09, 2011
    You are just right echoDreamz. This is just a sample that shows how to create a cert request. If you need your cert to have specific extensions and properties (like the usage of the cert), you will need to modify the sample to fit your needs.Regards,Alex

  • Anonymous
    December 16, 2011
    Hi,Thanks for the article. It helped me a lot!. Can you please tell me how I can update some of the certificate properties / request properties such as FirstName, LAstName, mainily  "RequesterName" and "Request Email Address" properties of the request while submitting a request to the Enterprise Issuing CA.Thanks,VR

  • Anonymous
    December 18, 2011
    Hi VR,Check this property of the request:IX509CertificateRequestPkcs7::RequesterName propertymsdn.microsoft.com/.../aa377633(v=vs.85).aspxFor Request Email Address I would need to investigate. And for that I would need a Technical Support case, as I don't have much free time to check this out.Regards,Alex

  • Anonymous
    December 19, 2011
    Hi Alex,Thank you for your quick response. If I use XEnroll.dll(the one supported on Server2003 as opposed to CEnroll.dll) and I am not creating the PKCS#10, instead obtaining an already created CSR via IIS , submit to CA via the CCertRequest.Submit() method, then how do I set the RequesterName or any other cert properties such as Request.GiveName, Request.SurName, RequestEmailAddress etc..Please let me know your findings with your technical support ticket on methods to set the request/certificate properties in CA considering it all running on a Server2003 environment.Your help is greatly appreciated!Thanks,VR

  • Anonymous
    December 19, 2011
    Hi VR,"Please let me know your findings with your technical support ticket"I don't think you understood me well. I don't have any support ticket and I cannot create one. My customers are the ones who create the tickets for me or my colleagues to work on the issues.Do you need help right now?blogs.msdn.com/.../do-you-need-help-right-now.aspxI won't be able to take on new work until Jan 2nd 2012, but my colleagues may be able to assist too. Just note that XEnroll is obsolete and support to Windows Server 2003 is very, very limited.Regards,Alex

  • Anonymous
    January 19, 2012
    In unmanaged version CX509Enrollment:Install:InstallResponse() returns different Return Codes that can differentiate potential errors.Managed version doesn't return any feedback.Are there specific exceptions I can catch and what they indicate?Thank you in advance.

  • Anonymous
    February 15, 2012
    The comment has been removed

  • Anonymous
    February 15, 2012
    Hi James,I would need to debug the issue to figure out what is going on exactly. Please feel free to open a case with MS Technical Support so we are able to assist you properly.Thx!Alex

  • Anonymous
    March 22, 2012
    The following sequence is not recommended: objCSP.InitializeFromName("Microsoft Enhanced Cryptographic Provider v1.0"); objCSPs.Add(objCSP); objPrivateKey.CspInformations = objCSPsThe CspInformations collection is expected to be empty or to contain all CSPs available on the machine.The proper way to target a specific CSP is: objPrivateKey.ProviderName = "Microsoft Enhanced Cryptographic Provider v1.0";

  • Anonymous
    March 23, 2012
    The objCertConfig.GetConfig(CC_UIPICKCONFIG); call throws "CCertConfig::GetConfig: No more data is available. 0x80070103 (WIN32/HTTP: 259)"I'm assuming this is because I'm not a member of the domain.  Can I get a cert from a domain CA on a system that is not a member of the domain?

  • Anonymous
    May 14, 2012
    Hi Alex,If I need to create .p7b file, from your code do I simply filestream the strCert string obtained via GetCertificate(CR_OUT_BASE 64 | CR_OUT_CHAIN) with the file extension .p7b?  Please help!Thanks,VR

  • Anonymous
    May 15, 2012
    Hi VR,Some info on how to export the cert with its private key and its cert chain here:How to export our enrolled certificates programmaticallyblogs.msdn.com/.../how-to-export-our-enrolled-certificates-programmatically.aspxYou may use this flag to export the entire cert chain:PFXExportOptions enumerationmsdn.microsoft.com/.../aa379073(v=vs.85).aspx"PFXExportChainWithRootIncludes the entire certificate chain, including the root certification authority certificate."Regards,Alex

  • Anonymous
    May 15, 2012
    Hi VR,If you don't need the private key, but only the public part of the cert and its cert chain, this method that you mentioned should do the work according to our docs:ICertRequest3::GetCertificate methodmsdn.microsoft.com/.../aa385046(v=vs.85).aspx"The GetCertificate method returns the certificate issued for the request as an X.509 certificate, or optionally packaged in a Public Key Cryptography Standards (PKCS) #7 message that contains the complete certificate chain for the Certificate Services server."Regards,Alex

  • Anonymous
    May 16, 2012
    The comment has been removed

  • Anonymous
    May 16, 2012
    The comment has been removed

  • Anonymous
    May 16, 2012
    Thank you so much Alex. You answered my question, I got it working.Thanks again for all your help. I really appreciate it.Regards,VR

  • Anonymous
    June 21, 2012
    Hi Ales, i have a problem with your code and the error is in the sendRequest:Denied by Policy Module  0x80094801, The request does not contain a certificate template extension or the CertificateTemplate request attribute.Thanks for your help!DM

  • Anonymous
    June 21, 2012
    Hi Alex, i have a problem with your code and the error is in the sendRequest:Denied by Policy Module  0x80094801, The request does not contain a certificate template extension or the CertificateTemplate request attribute.Thanks for your help!DM

  • Anonymous
    June 21, 2012
    Hi DM,If I recall well, this sample doesn't use cert templates, so the error is to be expected if your CA requires them. This other sample shows how to use cert templates:How to request an smartcard logon cert programmatically (C#)blogs.msdn.com/.../how-to-request-an-smartcard-logon-cert-programmatically-c.aspxRegards,Alex

  • Anonymous
    July 21, 2012
    The comment has been removed

  • Anonymous
    July 22, 2012
    Hi RA,On WinXP/Server 2003 you need to use XEnroll instead of CertEnroll. Unfortunatelly I don't have any sample for XEnroll, mainly because it has been deprecated for years.If you need help with XEnroll, I suggest you open a case with Microsoft Technical Support.Regards,Alex

  • Anonymous
    August 02, 2012
    Hi Alex,Thanks for your reply i got the code for XEnroll .My CA server is configured on windows 2008 and for development we are using windows xp .my biggest worry is i'm generating my certificate request using XEnroll and sending to CA for signing who have CertEnroll.will this scenario work? or do i need to use windows 2008 for development where I can find CertEnroll dll.Please replyThanksRA

  • Anonymous
    August 03, 2012
    Hi All/AlexPlease reply...Can I generate certificate using windows 2003/XP(where i have XEnroll ) and send to CA server which is into windows server 2008(where we have CertEnroll). Will this work or give error....Please helpThanksin advanceRA

  • Anonymous
    August 05, 2012
    Hi RAfsar,Here you have the answer to your question:support.microsoft.com/.../922706Basically you can use XEnroll to request certs on WinServer 2008, but with reduced functionality (cannot tell which functionality you will be missing exactly, though).Regards,Alex

  • Anonymous
    August 06, 2012
    Thank you very much Alex...........

  • Anonymous
    August 26, 2012
    Hi All,When i'm submitting my request to CA my request is going into pending folder .iDisposition = objCertRequest.Submit(                   CR_IN_BASE64 | CR_IN_FORMATANY,                   strRequest,                   null,                   strCAConfig               );I'm getting iDisposition =5 which is pending .Am i doing any thin wrong how to issue the certificate directly i mean not to pending stage.ThanksRizwan

  • Anonymous
    August 26, 2012
    Hi Rizwan,That should be something to configure on the server. CAs can issue certs directly or wait for an admin's approval.Regards,Alex

  • Anonymous
    August 27, 2012
    Thanks Alex for your quick help,Once it is pending and approved by Admin then how to fetch the same request which is now signed by CA server?I must be very much thank full to you for your blog this has helped me a lot.ThanksRizwan

  • Anonymous
    August 28, 2012
    We have resolved this issue you were right we need to make some changes into the config on CA and it started working.ThanksRizwan

  • Anonymous
    August 30, 2012
    Hi Alex,Now i've generated CSR and got it signed back from CA server.When I'm trying to convert into Xenroll.CreatePFXfile("Password",certPath) i get error that this is not possible with current key.I'm able to successfully import that certificate into certificate store.When i go to certificate store and try to export certificate private key manually so i find that option grayed out.Any idea for this issue.Because i wanted to extract my private key from signed certificate and make it password protected and send to mail.ThanksRizwan

  • Anonymous
    September 02, 2012
    Hi Rizwan,You need to mark your key as exportable when creating the request. There are flags for that as you can see here:blogs.msdn.com/.../certenroll-cx509enrollment-p-createrequest-returns-error-0x8009000b.aspxRegards,Alex

  • Anonymous
    September 03, 2012
    Thanks Alex for all your help, it worked and i'm able to generate certificate and convert to .pfx file.Any Idea how to revoke the certificate which CA has issued?I was looking and  found the command through certutill.exe ,but same i wanted to do through my c# code.Please guide.Thanks in advance for all your help so far.Rizwan

  • Anonymous
    September 03, 2012
    Hi Rizwan, I don't have any sample to revoke certs, but I guess you can use this method:ICertAdmin2::RevokeCertificate methodmsdn.microsoft.com/.../aa383251(VS.85).aspxHere you have a sample that shows how to use certadmin in .NET, in case it helps as a base:blogs.msdn.com/.../how-to-export-issued-certificates-from-a-ca-programatically-c.aspx

  • Anonymous
    September 04, 2012
    Thanks Alex for all your help and quick response for my queries...I'm creating .PFX file using xenroll.createpfxfile which accepts password and file path.I've a requirement to createpfx file without password.Any idea how to do that using xenroll.dllThanksRizwan

  • Anonymous
    September 04, 2012
    Hi Rizwan,I don't remember much about xenroll, as it has been deprecated for years, but I would have assumed that passing "" or null as the password would do...

  • Anonymous
    September 04, 2012
    The comment has been removed

  • Anonymous
    September 06, 2012
    The comment has been removed

  • Anonymous
    September 21, 2012
    Thank you very much for your blog and your quick response ,this blog actually helped me a lot.You are really great.ThanksRizwan

  • Anonymous
    October 02, 2012
    certEnroll.createPKCS10(dn, ClientAuthentication)method is working fine when called using console app but on IIS server its not working the moment its coming here and throwing exceptionException : The system cannot find the file specified. (Exception from HRESULT: 0x80070002)Any help pleaseThanksRizwan

  • Anonymous
    October 02, 2012
    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

  • Anonymous
    October 08, 2012
    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 NameWindows 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 .ThanksRizwan

  • Anonymous
    October 08, 2012
    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.ThanksRizwan

  • Anonymous
    October 10, 2012
    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.ThanksRizwan

  • Anonymous
    January 30, 2013
    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.

  • Anonymous
    January 30, 2013
    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

  • Anonymous
    January 30, 2013
    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

  • Anonymous
    January 30, 2013
    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

  • Anonymous
    February 05, 2013
    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.

  • Anonymous
    March 19, 2013
    The comment has been removed

  • Anonymous
    May 19, 2013
    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..

  • Anonymous
    May 21, 2013
    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

  • Anonymous
    May 25, 2013
    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

  • Anonymous
    September 18, 2013
    How to add a new property in ICertProperties. Can you please reply its very urgent.Thanks in advance.

  • Anonymous
    October 21, 2013
    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

  • Anonymous
    December 04, 2013
    Thanks for your amazing and unique blog post about this subject. I successfuly implemented your code. But still have a little but disturbing problem.I just want to create CSR and Private Key. I won't use our CA servers to generate and install certificate. CSR created successfuly but private key didn't. I asked my question at Stackoverflow, i hope you can help me. stackoverflow.com/.../generating-csr-and-exporting-private-key-with-c-sharp

  • Anonymous
    December 19, 2013
    The intent of the CspInformations collection property on the private key class is to include all CSPs installed on the system, and that’s merely an optimization to prevent multiple CSP enumerations when enrolling for multiple certs.Since the above sample targets one CSP, set the private key class ProviderName string property to the CSP name and avoid creating the CspInformation object and collection object.This directly tells the private key class to use that CSP.Specifying a collection of CSPs tells the Pkcs10 request class to first sort the CSPs in the collection, assign priorities, enumerate in priority order, then pick the first one that can successfully create a new key.That’s a lot of work when you already know which CSP to use.

  • Anonymous
    December 19, 2013
    After calling objCertRequest.Submit:1) use objCertRequest.GetLastStatus to get an HRESULT error code from the CA.  If not S_OK, this HRESULT will help explain why the request was denied.  Pass it to objCertRequest.GetErrorMessageText to obtain localized error message text for the HRESULT.2) use objCertRequest.GetDispositionMessage to obtain server supplied informational/explanatory message text that may be present even when the cert was issued.

  • Anonymous
    February 10, 2014
    I am trying to generate certificate using <CertEnroll in Asp.netWhile calling CreateRequest(), I am getting the below error every time.var enroll = new CX509Enrollment();//Code to Initialize and assign certificate namestring csr = enroll.CreateRequest();Error:CertEnroll::CX509Enrollment::_CreateRequest: Access is denied. 0x80070005 (WIN32: 5 ERROR_ACCESS_DENIED)Please help as I am stuck at this point.

  • Anonymous
    March 07, 2014
    I am trying to add SAN values to a CSR provided by the user, I am passing the san values in the strAttributes parameter on objCertRequest.Submit . but after the cer file is generated the san are not being displayed on the certificate generated.Any help will be appreciated .Thanks

  • Anonymous
    March 26, 2014
    Hello,I am trying to export private key via code like this:objCSP.InitializeFromName(cryptograficProvider);               //  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 = "CertEnrolment API test 1";               objPrivateKey.Length = 2048;               objPrivateKey.KeySpec = X509KeySpec.XCN_AT_KEYEXCHANGE;               objPrivateKey.KeyUsage = X509PrivateKeyUsageFlags.XCN_NCRYPT_ALLOW_ALL_USAGES;               objPrivateKey.ExportPolicy = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;               objPrivateKey.MachineContext = true;               //  Provide the CSP collection object (in this case containing only 1 CSP object)               //  to the private key object               objPrivateKey.CspInformations = objCSPs;               //objPrivateKey.SecurityDescriptor = "Administrator";               //  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.ContextAdministratorForceMachine,                   objPrivateKey,                   "TestUser"               );               objPkcs10.PrivateKey.Export("BCRYPT_PUBLIC_KEY_BLOB");But still i am getting error:CertEnroll::CX509PrivateKey::Export: This function is not supported on this system. 0x80070078 (WIN32/HTTP: 120 ERROR_CALL_NOT_IMPLEMENTEDHave any idea what is wrong?BR,Lubomir

  • Anonymous
    March 28, 2014
    After some fighting I found the problem. In source code bcrypt.h is BCRYPT_PUBLIC_KEY_BLOB defined as#define BCRYPT_PRIVATE_KEY_BLOB      L"PRIVATEBLOB"Correct call is:     objPkcs10.PrivateKey.Export("PRIVATEBLOB");then private key is exported :)

  • Anonymous
    July 06, 2014
    The code sample doesn't compile in VS2013 ("The type 'CERTENROLLLib.CX509CertificateRequestPkcs10Class' has no constructors defined" and "Interop type 'CERTENROLLLib.CX509CertificateRequestPkcs10Class' cannot be embedded. Use the applicable interface instead.")

  • Anonymous
    August 18, 2014
    Hey Alex,Can we update any certificate request from pending to Issued using C#.If yes then how?Thanks

  • Anonymous
    November 11, 2014
    Anyone have an idea why taking the code here and specifying the private key algorithm as shown in the example onCObjectId algobj = new CObjectId();algobj.InitializeFromAlgorithmName( ObjectIdGroupId.XCN_CRYPT_ANY_GROUP_ID, ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlags.AlgorithmFlagsNone, "ECDSA_P521");objPrivateKey.Algorithm = algobj;Each time the result is "Cannot find object or property. 0x80092004 (-2146885628)"This is on windows 7 64-bit.Thanks

  • Anonymous
    December 28, 2014
    Hi Alex, hi VR, how do I set the RequesterName or any other cert properties such as Request.GiveName, Request.SurName, RequestEmailAddress etc..Here is the reference: msdn.microsoft.com/.../cc226759.aspxRequest_Email: Column name "Request.EMail". The EmailAddress attribute of the DN from the Subject of the certificate request.So just provide the values in the DN of the certificate request.

  • Anonymous
    December 28, 2014
    @JugdeepSingh msdn.microsoft.com/.../aa383250%28v=vs.85%29.aspx