title: How can I generate an Extended Validation self-signed certificate with CertEnroll?
body: <p>Due to a bug in Windows Azure, all self-signed client certificates used with the Azure REST API from a Windows 8 application must be specified as extended validation certificates.</p>
  
  <p>To provide a better user experience, I am trying to generate this self-signed certificate on a remote server. I'm using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa374863%28v=vs.85%29.aspx" rel="nofollow noreferrer">Certificate Enrolment API</a>, a COM library distributed as part of Windows, as described in <a href="https://stackoverflow.com/a/13806300/138578">this answer</a> to the question <a href="https://stackoverflow.com/q/13806299/138578">How to create a self-signed certificate using C#?</a></p>
  
  <p>The code is largely the same, just slightly modified for my own use:</p>
  
  <pre><code>public static X509Certificate2 CreateSelfSignedCertificate(
      string cname,
      string friendlyName,
      string password)
  {
      // create DN for subject and issuer
      var dn = new CX500DistinguishedName();
      dn.Encode("CN=" + cname, X500NameFlags.XCN_CERT_NAME_STR_NONE);
  
      // create a new private key for the certificate
      CX509PrivateKey privateKey = new CX509PrivateKey();
      privateKey.ProviderName = "Microsoft Base Cryptographic Provider v1.0";
      privateKey.MachineContext = true;
      privateKey.Length = 2048;
      privateKey.KeySpec = X509KeySpec.XCN_AT_SIGNATURE; // use is not limited
      privateKey.ExportPolicy 
          = X509PrivateKeyExportFlags.XCN_NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
      privateKey.Create();
  
      // Use the stronger SHA512 hashing algorithm
      var hashobj = new CObjectId();
      hashobj.InitializeFromAlgorithmName(
          ObjectIdGroupId.XCN_CRYPT_HASH_ALG_OID_GROUP_ID,
          ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, 
          AlgorithmFlags.AlgorithmFlagsNone,
          "SHA512");
  
      // Create the self signing request
      var cert = new CX509CertificateRequestCertificate();
      cert.InitializeFromPrivateKey(
          X509CertificateEnrollmentContext.ContextMachine,
          privateKey,
          string.Empty);
  
      cert.Subject = dn;
      cert.Issuer = dn; // the issuer and the subject are the same
      cert.NotBefore = DateTime.Now;
      cert.NotAfter = DateTime.Now.AddYears(50); 
      cert.HashAlgorithm = hashobj;
  
      var clientAuthenticationOid = new CObjectId();
      clientAuthenticationOid.InitializeFromValue("1.3.6.1.5.5.7.3.2");
  
      // Set up cert to be used for Client Authentication.
      var oids = new CObjectIds();
      oids.Add(clientAuthenticationOid);
  
      var eku = new CX509ExtensionEnhancedKeyUsage();
      eku.InitializeEncode(oids);
  
      cert.X509Extensions.Add((CX509Extension)eku);
  
      // Add the certificate policy.
      var policy = new CCertificatePolicy();
      policy.Initialize(clientAuthenticationOid);
  
      // THIS IS WRONG - NEEDS A DIFFERENT QUALIFIER
      var qualifier = new CPolicyQualifier();
      qualifier.InitializeEncode(
          "c0",
           PolicyQualifierType.PolicyQualifierTypeUserNotice);
  
      policy.PolicyQualifiers.Add(qualifier);
  
      var policies = new CCertificatePolicies();
      policies.Add(policy);
  
      var ecp = new CX509ExtensionCertificatePolicies();
      ecp.InitializeEncode(policies);
  
      cert.X509Extensions.Add((CX509Extension)ecp);
  
      cert.Encode();
  
      // Do the final enrolment process
      var enroll = new CX509Enrollment();
      enroll.InitializeFromRequest(cert); // load the certificate
      enroll.CertificateFriendlyName = friendlyName;
      string csr = enroll.CreateRequest(); // Output the request in base64
  
      // and install it back as the response
      enroll.InstallResponse(
          InstallResponseRestrictionFlags.AllowUntrustedCertificate,
          csr,
          EncodingType.XCN_CRYPT_STRING_BASE64,
          ""); // no password
  
      // output a base64 encoded PKCS#12 for import to .NET
      var base64encoded = enroll.CreatePFX(
          password,
          PFXExportOptions.PFXExportChainWithRoot);
  
      // instantiate the target class with the PKCS#12 data
      return new X509Certificate2(
          System.Convert.FromBase64String(base64encoded),
          password,
          X509KeyStorageFlags.Exportable);
  }
  </code></pre>
  
  <p>I've found the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa375225%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>ICertificatePolicy</code></a> interface which appears to represent the right type of structure, but I can't deduce the right <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa376803%28v=vs.85%29.aspx" rel="nofollow noreferrer"><code>IPolicyQualifier</code></a> to use. In my code, the qualifier is </p>
  
  <p>For clarity, this where you configure the information in the Windows 8 Certificate Manager:</p>
  
  <p><img src="https://i.stack.imgur.com/iXRtW.png" alt="where to enable extended validation"></p>
  
  <p>Which produces this property on the certificate:</p>
  
  <p><img src="https://i.stack.imgur.com/rTb86.png" alt="extended validation property on a certificate"></p>
  
  <p>My code currently produces this property:</p>
  
  <p><img src="https://i.stack.imgur.com/mGHR2.png" alt="not quite extended validation property on a certificate"></p>
  
  <p>Close, but not there yet.</p>
  
  <p>Is there another way to load data into the <code>IPolicyQualifier</code> so that it produces the expected result, perhaps using the InitialiseDecode method?</p>