Decrypt my World

Cryptography, Security, Debugging and more!

How to create a certificate request with CertEnroll (JavaScript)

How to create a certificate request with CertEnroll (JavaScript)

Rate This
  • Comments 54

Hi all,

The following Javascript sample shows how to use CertEnroll COM component to create a certificate request:

<html>
<head>
    <title>Certificate Request test</title>
</head>
<body> 
  <object id="objCertEnrollClassFactory" classid="clsid:884e2049-217d-11da-b2a4-000e7bbb2b09"></object>    
  <script language="javascript">

    function CreateRequest() 
    {
      document.write("<br>Create Request...");                      

      try {
        // Variables
        var objCSP = objCertEnrollClassFactory.CreateObject("X509Enrollment.CCspInformation");
        var objCSPs = objCertEnrollClassFactory.CreateObject("X509Enrollment.CCspInformations");
        var objPrivateKey = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509PrivateKey");
        var objRequest = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509CertificateRequestPkcs10")
        var objObjectIds = objCertEnrollClassFactory.CreateObject("X509Enrollment.CObjectIds");
        var objObjectId = objCertEnrollClassFactory.CreateObject("X509Enrollment.CObjectId");
        var objX509ExtensionEnhancedKeyUsage = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509ExtensionEnhancedKeyUsage");
        var objExtensionTemplate = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509ExtensionTemplateName")
        var objDn = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX500DistinguishedName")
        var objEnroll = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509Enrollment")

        //  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 = 1; // AT_KEYEXCHANGE = 1

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

        // Initialize P10 based on private key
        objRequest.InitializeFromPrivateKey(1, objPrivateKey, ""); // context user = 1

        // 1.3.6.1.5.5.7.3.2 Oid - Extension
        objObjectId.InitializeFromValue("1.3.6.1.5.5.7.3.2");
        objObjectIds.Add(objObjectId);
        objX509ExtensionEnhancedKeyUsage.InitializeEncode(objObjectIds);
        objRequest.X509Extensions.Add(objX509ExtensionEnhancedKeyUsage);

        // 1.3.6.1.5.5.7.3.3 Oid - Extension
        //objExtensionTemplate.InitializeEncode("1.3.6.1.5.5.7.3.3");
        //objRequest.X509Extensions.Add(objExtensionTemplate);

        // DN related stuff
        objDn.Encode("CN=alejacma", 0); // XCN_CERT_NAME_STR_NONE = 0
        objRequest.Subject = objDn;

        // Enroll
        objEnroll.InitializeFromRequest(objRequest);
        var pkcs10 = objEnroll.CreateRequest(3); // XCN_CRYPT_STRING_BASE64REQUESTHEADER = 3

        document.write("<br>" + pkcs10);
        document.write("<br>The end!");
      }
      catch (ex) {
        document.write("<br>" + ex.description);
        return false;
      }

      return true;
    }       

    CreateRequest();

  </script>
    
</body>
</html>

And the following Javascript sample shows how to install the response from the CA (Certificate Authority):

<html>
<head>
    <title>Certificate Request test</title>
</head>
<body> 
  <object id="objCertEnrollClassFactory" classid="clsid:884e2049-217d-11da-b2a4-000e7bbb2b09"></object>    
  <script language="javascript">

  function InstallCert() 
  {        
    document.write("<br>Installing certificate...");                      

    try {
    // Variables
    var objEnroll = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509Enrollment")
    var sPKCS7 = "-----BEGIN CERTIFICATE-----" +
    "MIIKFQYJKoZIhvcNAQcCoIIKBjCCCgICAQExADALBgkqhkiG9w0BBwGgggnqMIIF" +
    "QjCCBCqgAwIBAgIKYbzdPwAAAAAAVzANBgkqhkiG9w0BAQUFADBJMRMwEQYKCZIm" +
...
    "h25CSWewZhpgbZkKPATLzidc0EjrWLl74RU32HEqkl2+R7yAdBQjMQA=" +
    "-----END CERTIFICATE-----"

    objEnroll.Initialize(1); // ContextUser
    objEnroll.InstallResponse(0, sPKCS7, 6, ""); // AllowNone = 0, XCN_CRYPT_STRING_BASE64_ANY = 6
    }
    catch (ex) {
      document.write("<br>" + ex.description);
      return false;
    }

    return true;
  }

  InstallCert(); 
     
  </script>

</body>
</html>

Note: this code must be run in the same machine where we made the request.

Note: these samples just create the request and install the response from the CA. If we need to send the request to the CA and get its response programmatically, the following C# sample may help with the objects and methods we can use to achieve this: How to create a certificate request with CertEnroll and .NET (C#).

I hope this helps.

Regards,

 

Alex (Alejandro Campos Magencio)

  • Hi,

    great article, it was really helpful!

    I have a small doubt, though: I am creating a request using a Smart Card reader and I have noticed that after invoking CreateRequest() a request is inserted in the card. This was not the case with xenroll under Windows XP.

    Is this the expected behavior? Can I prevent CreateRequest() from inserting the request in the card?

    Thanks and keed posting!

  • Would you be able to help me create a asp script to generate a CSR for a IIS entry.  And another script to install the cert purchased from GeoTrust?  How much would you charge for something like this? Please email me at erwinyu888@hotmail.com

  • People open incidents/cases with MS Technical Support in their respective countries, and if the country is in my area and the question is related to the technologies that my team supports, I may take the case. Otherwise colleagues of mine will take it. I don't support IIS related stuff, for instance. Another team does.

    Additionally, I can't tell how much MS charges for these services. Also take into account the following limitations:

    1) This kind of "How to" questions are called Advisories, they are not support incidents, and only customers with a Premier contract with Microsoft can open them. They are charged by the hour.

    2) We won't create custom code, we will only provide with samples/documentation to assist customers to create their own production code.

    If you have any question though, feel free to contact MS Technical Support.

    Thx,

    Alex

  • That code doesn't work in html frames, I think. In my case appears the message "CertEnroll::CX509EnrollmentWebClassFactory::CreateObject: Unspecified error 0x80004005 (-2147467259)" and Certenroll don't load, If I don't use frames it works great.

  • This is a great little article. I appreciate the sample code as I am finding it very hard to find sample code for certenroll.

    One question: I have this all working, but when I go to install the certificate I have generated (I work for QuoVadis Limited who is a certificate authority so am using a dev CA to generate the certificate) I get the following error:

    "CertEnroll::CX509Enrollment::p_InstallResponse: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider 0x800b0109 (-2146762487)"

    I have the root and issuing CA certs installed on the PC and I even tried installing a PEM with chain version of the certificate that includes the root and issuing CA certificates, but I am still getting this error. Any idea why this is happening?

    Any help with this would be greatly appreciated!

    Cheers,

    Craig Martin

    VP Software Development

    QuoVadis Limited

  • I'm not sure without knowing the details of your environment or debugging the code itself, but this could be related:

    Error message when a user uses Internet Explorer 7 to open the certificate enrollment Web page to install an end entity certificate on a Windows Vista-based client computer

    http://support.microsoft.com/default.aspx?scid=kb;EN-US;945121

    If that doesn't help, I suggest you open a case with us, Microsoft Technical Support. If you are in EMEA region, I may assist you personally.

    Cheers!

  • I copied this code to an aspx file and get

    Object doesn't support this property or method

    in line

    var objCSP = objCertEnrollClassFactory.CreateObject("X509Enrollment.CCspInformation");

    with win 7

    any idea why ?  

  • my mistake. it was IE security. Thanks for the nice article

  • Hi, I get this error. what could this mean? i've tried IE security to enable all possible tweaks.

    Thanks!

    --------------------------

    Webpage error details

    User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)

    Timestamp: Tue, 22 Dec 2009 06:33:55 UTC

    Message: CertEnroll::CX509EnrollmentWebClassFactory::CreateObject: The operation was canceled by the user. 0x800704c7 (WIN32: 1223)

    Line: 43

    Char: 9

    Code: 0

    URI: https://intranet/user/mycertrequestIE.php

  • Hi Craig,

    Your Answer is

               objEnroll.InstallResponse(0x00000004, cert, 6, ""); // AllowUntrustedRoot = 4

    If your root certificate is not trusted. You may use AllowUntrustedRoot instead of AllowNone (=0)

    Hi Jay, you should look at security restrictions about Activex. When you enable/prompt download unsigned activex controls it should work.

    I have another question; I can create request and install certificate. I see the certificate in my certificates. But when the user goes to the web site no certificate windows pops up. If I force popup via capicom, I do not see the installed certificate in the popup list. Any idea why?

  • Emre, maybe it has to do with the available usages of that cert...

  • Hello again,

    With some support from MS, I learned that some changes to above code should be done.

    First of all key length should be 2048 and keyspec should remain default (unchanged)

    So if you update the certificate request like this it should work.

    objPrivateKey.Length = 1024;

    //objPrivateKey.KeySpec = 1; // AT_KEYEXCHANGE = 1

  • Hi--

    I used info from this code as well as from various other sources to update our CA request code to work with Vista/IE7, and now I sat down at a new Win7/IE8 system to test it out (hoping it'd be fine with presumably the same CertEnroll stuff and major version number), but instead I get:

    Can't create CSP List Object!  Error: -2147467259 :CertEnroll::CX509EnrollmentWebClassFactory::CreateObject: Unspecified error 0x80004005 (-2147467259)

    and the crypto provider list, which is filtered down to "MS Enhanced Crypto Provider v1.0" on XP/Vista, is empty.

    Tried making sure the dev CA was trusted but still generates the same response.

    What's different between Vista and Win7?  Or is it between IE7 and IE8?  Some browser security setting, or CLASSID change, or what?

    Thanks,

    Stephen

  • Actually, I guess I should have dug deeper, but just pulled the frame URLs out for requesting and installing a cert and went directly and Rafael's right, it works without a hitch that way!  So what's going on here?  Works in Vista with frames, only works in Win7 without frames.  Our CA uses frames and any requirement to change that is likely to be a pain.

    Any ideas?

    Thanks,

    Stephen

  • I really can't tell why you are getting that error with frames. I would have to debug the issue, and for that I would need a support case to work with... You if you need help, I suggest you open a case with us.

    Thx,

    Alex

Page 1 of 4 (54 items) 1234
Leave a Comment
  • Please add 7 and 4 and type the answer here:
  • Post
Translate This Page