see sharp RSS 2.0
# Friday, 28 February 2014

A small utility that signs federation metadata.

MetadataSigner[1].zip (56.86 KB)
it requires .NET 4.5

Friday, 28 February 2014 11:03:13 (Mitteleuropäische Zeit, UTC+01:00)  #    -
Authentication | Certificates
# Monday, 10 December 2012

Much more because I tend to forget these things all the time than anything else:

NET Stop certsvc
Net Start certsvc

then you can create a INF file with the following:


Subject="CN=<your real hostname here>"


CertificateTemplate="<your templatename here>"

SAN="DNS==<your real hostname here>&DNS=<hostname1>&DNS=<hostname2>"


Monday, 10 December 2012 14:17:28 (Mitteleuropäische Zeit, UTC+01:00)  #    -
CA | Certificates | Registry
# Monday, 04 April 2011

i wrote about parsing the san of a certificate before, here is another way to do it:

1) add a reference to CertEnroll 1.0 Type Library

2) use IX509ExtensionAlternativeNames to get a collection of IAlternativeName objects

3) get the data using the IAlternativeName.strValue and IAlternativeName.Type attributes

 Here's an example:

private string GetSAN(X509Certificate2 cert)
        X509Extension ext = cert.Extensions[""]; // get the SAN extension

        if (null != ext)
                string temp = string.Empty;
                IX509ExtensionAlternativeNames an = new CX509ExtensionAlternativeNames();
                an.InitializeDecode(EncodingType.XCN_CRYPT_STRING_BASE64, Convert.ToBase64String(ext.RawData));
                foreach (IAlternativeName name in an.AlternativeNames)
                    temp += name.Type+":"+name.strValue+Environment.NewLine;
                return temp;                   
            catch (Exception ex)
                return ex.Message;
        return "no SAN present";
Monday, 04 April 2011 11:44:34 (Mitteleuropäische Sommerzeit, UTC+02:00)  #    -
C# | CAPI | Certificates
# Wednesday, 16 March 2011

If you have to parse the Subject Alternative Name (aka SAN) of a Certificate CertGetNameString is your friend:

[DllImport("crypt32.dll", EntryPoint = "CertGetNameString", CharSet = CharSet.Auto, SetLastError = true)]
static extern UInt32 CertGetNameString(
    IntPtr CertContext, 
    UInt32 lType, 
    UInt32 lFlags, 
    IntPtr pTypeParameter, 
    StringBuilder str, 
    UInt32 cch);

private const int CERT_NAME_EMAIL_TYPE = 1;
private const int CERT_NAME_UPN_TYPE = 8;
private const int CERT_NAME_NO_FLAG = 0;
private const int SIZE = 255;

private static void ParseSan(X509Certificate2 cc)
    Oid oid = new Oid("");
    X509Extension ext = cc.Extensions[oid.Value]; // get the SAN extension

    if (null != ext)
        StringBuilder Buffer = new StringBuilder(SIZE);               

        UInt32 nChars = CertGetNameString(cc.Handle,
        if (nChars == 1)
            nChars = CertGetNameString(cc.Handle,
        Console.WriteLine("{1}:'{0}'", Buffer.ToString(), cc.Thumbprint);

Wednesday, 16 March 2011 15:34:13 (Mitteleuropäische Zeit, UTC+01:00)  #    -
C# | CAPI | Certificates | P/INVOKE
# Wednesday, 24 June 2009

Sometime you need to get the integer value (or combination of values) for the Key Usage (i.e. for use in CertReq.EXE's INF files)

This is X509 Certificate Key Usage as defined in .NET:

Key Usage Description
0x0000 None
0x0001 EncipherOnly
0x0002 CrlSign
0x0004 KeyCertSign
0x0008 KeyAgreement
0x0010 DataEncipherment
0x0020 KeyEncipherment
0x0040 NonRepudiation
0x0080 DigitalSignature
0x8000 DecipherOnly

Of course it can be a combination of values :-)

To get it out of a certificate use this snippet (certificate is a valid X509Certificate2 object):

// either "Key Usage" or the OID "" can be used here
string keyUsageOID = "";

X509KeyUsageExtension keyUsageExtension = certificate.Extensions[keyUsageOID] as X509KeyUsageExtension;

if (keyUsageExtension != null)
   Console.WriteLine("Key Usage is 0x{0:x4}, {1}",

      // test for signature 
      bool hasSignatureKeyUsage = (keyUsageExtension.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.DigitalSignature;
      // just for fun: test for CRL signing too
      bool hasCrlSignKeyUsage = (keyUsageExtension.KeyUsages & X509KeyUsageFlags.CrlSign) == X509KeyUsageFlags.CrlSign;
// either Enhanced Key Usage or the OID
string enhancedKeyUsageOID = "";

X509EnhancedKeyUsageExtension enhancedkeyUsageExtension = certificate.Extensions[enhancedKeyUsageOID] as X509EnhancedKeyUsageExtension;

if (enhancedkeyUsageExtension != null)
   foreach (Oid oid in enhancedkeyUsageExtension.EnhancedKeyUsages)
      Console.WriteLine("Enhanced Key Usage is {0} ({1})",
Wednesday, 24 June 2009 09:51:50 (Mitteleuropäische Sommerzeit, UTC+02:00)  #    -
C# | Certificates
# Tuesday, 26 May 2009

Alejandro Campos Magencio has written a nice post on how to import a certificate without user interaction:

It is built around CryptUIWizImport which is described here:

Be sure to check all flags available:


Value Meaning

This function will perform the import based on the information in the CRYPTUI_WIZ_IMPORT_SRC_INFO structure pointed to by pImportSrc into the store specified by hDestCertStore without displaying any user interface. If this flag is not specified, this function will display a wizard to guide the user through the import process.


Suppress all user interfaces generated by cryptographic service providers (CSPs). This option can be overridden by the CRYPTUI_WIZ_NO_UI_EXCEPT_CSP option.


Suppress all user interfaces except those generated by CSPs. This option overrides the CRYPTUI_WIZ_IGNORE_NO_UI_FLAG_FOR_CSPS option.


Allow certificates to be imported.


Allow CRLs to be imported.


Allow CTLs to be imported.


Do not allow the user to change the destination certificate store represented by the hDestCertStore parameter.


Import the object to the certificate store for the local computer. This applies only to Personal Information Exchange (PFX) imports.


Import the object to the certificate store for the current user. This applies only to PFX imports.


Import the object to a remote certificate store. Set this flag if the hDestCertStore parameter represents a remote certificate store.

Tuesday, 26 May 2009 20:04:39 (Mitteleuropäische Sommerzeit, UTC+02:00)  #    -
C# | CAPI | Certificates
# Friday, 15 May 2009

First you need to enable the CA to accept SAN requests by changing the registry:

certutil -setreg policy\EditFlags +EDITF_ATTRIBUTESUBJECTALTNAME2

An nice description on how to enable SAN's on a MS CA can be found here.

I used that as a base to request WebServer certificates with certreq, but I had to remove the EncipherOnly line and I changed the Exportable flag to true in the INF file:

Signature="$Windows NT$

Subject = ""   
; must be the FQDN of domain controller
; EncipherOnly = FALSE
Exportable = TRUE         
; TRUE = Private key is exportable
KeyLength = 1024          
; Common key sizes: 512, 1024, 2048, 4096, 8192, 16384
KeySpec = 1               ; Key Exchange
KeyUsage = 0xA0          
; Digital Signature, Key Encipherment
MachineKeySet = True
ProviderName = "Microsoft RSA SChannel Cryptographic Provider"
ProviderType = 12
RequestType = CMC

; Omit entire section if CA is an enterprise CA
OID= ; Server Authentication

CertificateTemplate = WebServer
;Omit  line if CA is a stand-alone CA


The complete INF file syntax used by certreq can be found here:

EncipherOnly seems not to work in my 2008 environment or some other flags made that invalid.


In addition on creating the request, I specified the CA on the certreq commandline:

certreq -new request.inf certnew.req
certreq -config mycaserver\myca -submit certnew.req certnew.cer

the last line outputs the requestid needed for the next certreq command. Then, on the ca, issue the certificate if it is not automatically issued (depends on the template used).
after that you can retrieve & accept the the certificate:

certreq -config mycaserver\myca -retrieve myidreturendfromsubmitcommand certnew.cer
certreq -accept certnew.cer

After that, you have a certificate with multiple SAN's in your computers machine store (we specified MachineKeySet) which can be used in IIS.

Just to mention:

It's easy to add multiple Websites to IIS using hostheaders, but if you want to use SSL on those sites you have to add the SSL binding. The easiest i found was using the commandline. the commands depend on the version of your IIS.


cscript.exe c:\inetpub\adminscripts\adsutil.vbs set /w3svc/mysiteid/SecureBindings ":443:myhostheader"

The hostheader is pretty obvious, and the mysiteid can be found when you click on the WebSites node in the IIS manager (Its the Identifier column).


appcmd set site /"mysite" /+bindings.[protocol='https',bindingInformation='*:443:myhostheader]

Friday, 15 May 2009 10:00:26 (Mitteleuropäische Sommerzeit, UTC+02:00)  #    -
Authentication | Certificates | IIS
<2017 December>
About the author/Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.
Any link on this site may lead to an external website that is not under my control and that external website might show an opinion that is not mine.

© Copyright 2017
Hannes Köhler
Sign In
Total Posts: 39
This Year: 0
This Month: 0
This Week: 0
Comments: 1
All Content © 2017, Hannes Köhler
DasBlog theme 'Business' created by Christoph De Baene (delarou)