다음을 통해 공유


How to create a certificate request with CertEnroll (JavaScript)

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)

Comments

  • Anonymous
    March 03, 2009
    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!
  • Anonymous
    May 01, 2009
    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
  • Anonymous
    May 03, 2009
    The comment has been removed
  • Anonymous
    July 09, 2009
    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.
  • Anonymous
    October 26, 2009
    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 MartinVP Software DevelopmentQuoVadis Limited
  • Anonymous
    October 26, 2009
    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 computerhttp://support.microsoft.com/default.aspx?scid=kb;EN-US;945121If 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!
  • Anonymous
    December 15, 2009
    The comment has been removed
  • Anonymous
    December 15, 2009
    my mistake. it was IE security. Thanks for the nice article
  • Anonymous
    December 21, 2009
    The comment has been removed
  • Anonymous
    January 10, 2010
    Hi Craig,Your Answer is           objEnroll.InstallResponse(0x00000004, cert, 6, ""); // AllowUntrustedRoot = 4If 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?
  • Anonymous
    January 10, 2010
    Emre, maybe it has to do with the available usages of that cert...
  • Anonymous
    January 18, 2010
    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
  • Anonymous
    January 27, 2010
    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
  • Anonymous
    January 27, 2010
    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
  • Anonymous
    January 27, 2010
    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
  • Anonymous
    February 02, 2010
    Greetings all ,First of all its better to use objCertEnrollClassFactory before first use. In some cases (I don't remember which cases ) I had error and using below declaration helped.     var objCertEnrollClassFactory = document.applets(0);When using frames you may not access activex object directly and you may need to window.parent.document.applets(0);By the way if you have more than one activex/applet on your application you may need to use some other index than 0
  • Anonymous
    February 02, 2010
    I have a new problem; I can not install client certificate if there is a hierarchical chain for certificate server. Allow untrusted parameter which I mentioned above works only if you have standalone untrusted certificate server. Appreciate any help.
  • Anonymous
    February 13, 2010
    my comment above:Message: CertEnroll::CX509EnrollmentWebClassFactory::CreateObject: The operation was canceled by the user. 0x800704c7 (WIN32: 1223)was responded by emre as:you should look at security restrictions about Activex. When you enable/prompt download unsigned activex controls it should work.To emre or anyone:how do we enabled download unsigned activex controls? I've already dealt with the options in IE, are there any other settings in Windows7. I've seen some computer policies in gpo, but that didnt work either.I've used to do this in vista, In vista I can see the pop-up to confirm if the user wants to used unsigned active X, but I've never seen this in Windows7.any help is highly appreciated
  • Anonymous
    March 04, 2010
    The comment has been removed
  • Anonymous
    March 06, 2010
    Hello together,I have same issue as Jay on Windows 7:Message: CertEnroll::CX509EnrollmentWebClassFactory::CreateObject: The operation was canceled by the user. 0x800704c7 (WIN32: 1223)--> I tested it on Vista, too - there it works if you accept the activeX control prompt or add site to trusted.On Windows 7 it never works - reason seems to are higher restrictions for unsigned ActiveX controls. I also tried ActiveX Installation Service, where you can configure exceptions to general activeX handling rules - no effect.Has anyone successfully implemented and tested this for Windows 7?Thanks,Frank
  • Anonymous
    March 07, 2010
    Hello,for everyone who have the problem with frames and Windows 7 (in my case it was also the frame problem):It will work if CertEnroll Object is created in parent page and then accessed by framed page.Here some code to add it dynamically:Set both (parent and inner frame) via javascript to same document.domain value and then use parent.document.body.insertAdjacentHTML('afterBegin','<object id="objCertEnrollClassFactory_Proxy" classid="clsid:884e2049-217d-11da-b2a4-000e7bbb2b09" height=0 width=0></object> to insert the object to the parent frame. Than you can access it with objCertEnrollClassFactory = parent.objCertEnrollClassFactory_Proxy;Regards,Frank
  • Anonymous
    March 11, 2010
    Hi Frank,thanks for the answer, it works perfectly.
  • Anonymous
    March 23, 2010
    Hello all,I got an error mentioned erlier by Rafael:"Error: CertEnroll::CX509EnrollmentWebClassFactory::CreateObject: Unspecified error. 0x80004005 (-2147467259)."I use construction like this:"function certEnroll(){ this.classFactory= new ActiveXObject("X509Enrollment.CX509EnrollmentWebClassFactory"); this.objPrivKey = this.classFactory.CreateObject("X509Enrollment.CX509PrivateKey");}Code works fine in IE7 & IE8 on Vista.Error occurs on Windows 7 (IE8) only when I run it in separate window opened from parent window.I get question If i want to run ActiveX. that mean theActiveXObject is created but the CreateObejct method generates anexception.When I put url to my page direct into browser it works, but when I open new window by window.open() it doesn't.I put my page to trusted pages and set security level in IE settings to low.Any ideas to solve this problem?Thanks,Miiiiichal
  • Anonymous
    April 01, 2010
    Hi all--Just as an update, while I wasn't able to plug in Frank's suggestion as described, I was able to use it as the basis for something that does seem to have worked.  Still testing for verification purposes, but basically I ended up just moving the Object tag into the index.html file, then within the frames that would be using the object I ended up just adding the "parent." at the beginning of every reference.Somewhere I was having a problem trying to reassign the object from the parent level to something at the local level.  Probably just my own limited understanding of how to handle all that stuff (definitely not a VBS coder, or really much of a web page coder at all these days).Still checking on a potential minor issue or two with my resulting code, but looks like just moving the declaration/instantiation/whatever up to the parent document and calling it from there within the frames, was the critical piece.Thanks for the suggestion, Frank.Stephen
  • Anonymous
    April 14, 2010
    The comment has been removed
  • Anonymous
    April 19, 2010
    I can only get this to work under ie8 and windows 7 if i make it a trusted site and I set the security setting to allow the initialisation of active x controls not marked as safe for scripting. I don't mind making it a trusted site but I can't ask my user to enable active x controls not marked as safe for scripting. Any suggestions?
  • Anonymous
    April 21, 2010
    The comment has been removed
  • Anonymous
    May 06, 2010
    Please, not that previous solution won't work if both parent and child pages are not in the same domain.
  • Anonymous
    May 12, 2010
    CertEnroll is SiteLocked and will only work from HTTPS pages by default.
  • Anonymous
    May 24, 2010
    Good news!!! There is a fix available for the issue with frames that several people commented here. Check this other post of mine:CertEnroll control won't work when hosted inside a frame/iframe in IE8 (FIX)blogs.msdn.com/.../certenroll-control-won-t-work-when-hosted-inside-a-frame-iframe-in-ie8-fix.aspx
  • Anonymous
    May 24, 2010
    Hello, just wondering if you have any advice/example on how to create a certificate request using an existing key stored on the browser.In XP, I've used capicom to access the private key from a certificate stored in the browser and xenroll to create the certificate request.  However I haven't found the way to replicate the same behavior with certenroll.Any ideas?Many thanks,Cristian
  • Anonymous
    May 24, 2010
    I have no sample for that, sorry.
  • Anonymous
    June 14, 2010
    Hi--My code to make requests/imports works fine in Win7 now using my version of the workaround (referring to the parent page to access the object), with a little extra tweaking to make it flexible enough to work both within a frame and as a standalone page.However I just came up with another new issue I hadn't tested for before--the certificate apparently can't be imported when its validity period is in the future.  This is going to make things messy for us as we need to issue users their replacement certificates before their current one expires, generally, and to eliminate multiple valid certs, we issue with a validity period starting right after the expiration of the existing certificate.  This has never been a problem with any other browser/OS environment, but now it's been brought to my attention that it may not work in Win7.  Is this a hard setting, or something that can be configured for, or....?Any thoughts appreciated.Stephen
  • Anonymous
    June 29, 2010
    Hi again--Haven't seen any response on this question.  Any ideas at all?Stephen
  • Anonymous
    June 29, 2010
    Sorry Stephen, I don't know the answer to that without doing some research. I would need to spend time on this, and for that I need a support case. I suggest you open a case with us, Microsoft Technical Support.Regards,Alex
  • Anonymous
    July 01, 2010
    Alex--After weeks of no luck finding any insights about this issue, we did open a case this week.  Three days in and apparently we're still trying to fully get the nature of the problem across....Thanks,Stephen
  • Anonymous
    July 01, 2010
    Well, if I can be of any help, tell whoever is the owner of the case I'm willing to assist if needed.Regards,Alex
  • Anonymous
    July 02, 2010
    Alex--Thanks, we have a premiere incident opened and I've passed your name and offer to the person here to include in our next response on the case.    Is there any additional information we should give if they try to look for your help?Stephen
  • Anonymous
    July 02, 2010
    No, thx. I just located your case in our databases and I offered my help personally to the colleague in charge of it.Regards,Alex
  • Anonymous
    July 08, 2010
    On XP (and I think on Vista) I was able with CertEnroll to load a renewed certificate (same public key and name, new serial number and expiration date) into IE by calling InstallResponse(). Now with Win7 we get an error message -2146885628 with the same CA code. What is the correct way to install a renewed certificate, for which there is already a private key available? Does it need a special parameter, a different API, or is it not possible at all anymore? Has this functionality been intentionally turned off with Win7 ?Additionally, could you please explain, why CertEntroll is delivered as marked not Safe for Scripting? Is it not supposed to be used on websites? Or are trusted sites supposed to run code that is not marked Safe for Scripting? A lot of my users do not want to run code that is not marked as Safe for Scripting. Are there any plans to provide a CertEntroll (alternative) that is Safe for Scripting?
  • Anonymous
    July 08, 2010
    The comment has been removed
  • Anonymous
    November 06, 2010
    The comment has been removed
  • Anonymous
    November 12, 2010
    Is it feasible to submit the request to an Enterpise CA from the Javascript instead of C#?Thank you,~Gordon
  • Anonymous
    November 15, 2010
    I have successfully implemented this but unless I set the security settings in IE to Low for this site (and make it trusted) then I cannot get the control to run - I receive Object doesn't support this property or method.My users are not particularly savvy and so getting this to a state where it will run correctly is important - is this just a matter of signing the control?  (if so - how does one do that) or is there more to this than meets the eye?Thanks in advance -Yokai
  • Anonymous
    December 06, 2010
    >Is it feasible to submit the request to an Enterpise CA from the Javascript instead of C#?I found the answer to this, we can call ICertRequest3::Submit Method in javascript to use the DCOM interface for the CA vs HTTP post..~Gordon
  • Anonymous
    February 26, 2011
    How to install PKCS#7 in Smart Card?
  • Anonymous
    February 27, 2011
    You should use a smart card provider when making the request. My sample uses a non-smart card CSP.
  • Anonymous
    March 14, 2011
    How to install PKCS7# to Smart Card?Thanks!
  • Anonymous
    August 18, 2011
    Hello Friends,I need a help regarding installResponse(4,pkcs7,0,""); With windows 7 I get the following error asAccess Denied. Kindly do provide details of what need to done for this.
  • Anonymous
    October 11, 2011
           var objRequest = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509CertificateRequestPkcs10");       var objCertEnrollClassFactory = new ActiveXObject("X509Enrollment.CX509EnrollmentWebClassFactory");       var objPrivateKey = this.classFactory.CreateObject("X509Enrollment.CX509PrivateKey");       var objEnroll = objCertEnrollClassFactory.CreateObject("X509Enrollment.CX509Enrollment");       // Provide CSP information tp the private key object       //utilisation du CSP Gemalto       objPrivateKey.ProviderType = providerType ;       objPrivateKey.ProviderName  = providerName;       //  Provide key container name, key length and key spec to the private key object       objPrivateKey.Length = 1024;       objPrivateKey.KeySpec = 1; // AT_KEYEXCHANGE = 1       // Initialize P10 based on private key       objRequest.InitializeFromPrivateKey(1, objPrivateKey, ""); // context user = 1       objRequest.Subject = objDn;       // Enroll       objEnroll.InitializeFromRequest(objRequest);       var sPkcs10 = objEnroll.CreateRequest(1); // XCN_CRYPT_STRING_BASE64 = 1Lorsque j'appelle la fonction CreateRequest, j'obtiens l'erreur 80090020 qui signifie "Erreur interne".Je me demande si le problème peut venir de la configuration du poste client, ou de la privateKey, ou du CSP (Gemalto) ou du CA ....Quelqu'un peu m'aider ?
  • Anonymous
    October 11, 2011
    Irresistibledemon, Désolé, je ne parle pas français...
  • Anonymous
    October 11, 2011
    The comment has been removed
  • Anonymous
    October 12, 2011
    Hi Irresistibledemon,I cannot tell why that error happens exactly without debugging the issue. And for that I would need you to create a Technical Support Case so I can assist you. In any case, note that IE7 has some issues with CertEnroll: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 computersupport.microsoft.com/default.aspxWhy aren't you using IE9? (or IE8 if you are on XP?) It is way better than IE7.Regards,Alex
  • Anonymous
    January 22, 2014
    On IE10 and IE11 (Windows 7 and 8) insertAdjacentHTML does not add the necessary object to the top frame, therefore the workaround for windows 7 does not work anymore. In fact, even if I hardcode the object on the main frame it can not be accessed by getElementById.Does anyone knows a solution for this?