SSL Client Certificates and CAPICOM


This note describes how to access SSL client certificates using CAPICOM and P/Invoke to CryptoAPI from ASP.NET

The tasks described here include:

1. Creating and Installing a SSL server test certificate

The PSDK tool makecert.exe can be used to create a test self-signed SSL server certificate. Use a more recent version (5.131.3639.0+) to ensure all options are available. First, create the keys and associated certificate using any user account:
makecert  -sk "ssldemo" -pe  -r  -e "06/01/2004"  -sky Exchange
     -sy 12  -sp "Microsoft RSA SChannel Cryptographic Provider"
     -n "CN=localhost,OU=foounit,O=foodev"
     -ss MY -eku 1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2
This command generates a self-signed (-r) certificate with exportable (-pe) private key. An AT_KEYEXCHANGE 1024 bit RSA keypair is created in keycontainer "ssldemo". The keypair uses the RSA SCHANNEL provider type (-sy 12) and associated provider (-sp ..) The SubjectName is assigned Common Name "localhost" for local web-test purposes. The certificate is generated in the current user MY store. The ExtendedKeyUsages are specified as:
   Server Authentication (1.3.6.1.5.5.7.3.1)
   Client Authentication (1.3.6.1.5.5.7.3.2)
For other options, see the makecert.exe documentation.
The certificate should then be exported with private key using the Certs Snapin (or IE/Certs dialogs) into a password protected .pfx file for safe archiving off site. Don't forget to remove cert/key from CU | MY store.
For IIS configuration, log back in as administrator, and import the .pfx into the Machine | MY cert store. Since the cert is only self-signed and therefore the issuer (self) is not trusted, also import the public cert therein into Trusted Roots store. Now using the IIS configuration snapin, configure the web server to use SSL and also client certificates in:
   Default Web Site | Properties | Directory Security | Edit
For details, see:
Assigning an Existing Server Certificate to a Web Site in IIS 5.0

2. Creating and deploying the CAPICOM interop assembly

The CAPICOM interop assembly can be created automatically in VS.NET, or manually using the Framework SDK tool tlbimp.exe:
    tlbimp capicom.dll /namespace:CAPICOM /out:Interop.CAPICOM.dll
where capicom.dll is the native CAPICOM COM library. This command creates the interop assembly Interop.CAPICOM.dll with namespace "CAPICOM". To use the interop assembly from an ASP.NET application in the IIS environment, it should be deployed to the "bin" subdirectory to the virtual directory containing the ASP.NET (.aspx) application source code. Also, the ASP.NET code must reference the assembly for proper access. The interop assembly need NOT be Strong Name signed.

3. A basic ASP.NET application with CAPICOM and P/Invoke

To focus on the functionality, our aspx application will use the simplest possible structure returned page with no Windows Forms or controls and use simple Response.Write statements to return data. The ClientCert.aspx source code can be consulted for details.

To properly reference the CAPICOM interop assembly, to use its namespace and also to use P/Invoke services, the following ASP.NET directives are required in the source code:

<%@ Assembly Name="Interop.CAPICOM" %> <%@ Import Namespace="CAPICOM" %> <%@ Import Namespace="System.Runtime.InteropServices" %> Platform Invoke function declarations can be included in a <script runat=server> code block, or declared in a separate referenced class.

CAPICOM 2 has excellent support for accessing almost all useful properties of standard X509 v3 certificates. To use CAPICOM capability via .NET-COM interop from ASP.NET, we need to instantiate a CAPICOM certificate from the raw client certificate binary data available from .NET native classes.

ClientCert.aspx retrieves the client-submitted certificate in binary DER form into a byte array using the System.Web.HttpContext.Request.ClientCertificate.Certificate property. Since CAPICOM does not currently support instantiating a certificate directly from binary data, we need to either base64 encode the raw certificate into a string and use CAPICOM.Certificate.Import, or alternatively use P/Invoke to acquire a certificate context handle and instantiate a CAPICOM certificate using this handle. The latter approach is used here. We acquire a certificate context handle, pcertcntxt, using P/Invoke to CertCreateCertificateContext() passing in the raw certificate byte array. A CAPICOM certificate instance is initialized using the CAPICOM.Certificate.CertCntxt property. Now we can use all the properties and methods available within CAPICOM from ASP.NET.

Clientcert.aspx simply uses the CAPICOM Certificate methods Extensions() and ExtendedProperties() to retrieve enumerable collections of the standard certificate "Extensions" and CryptoAPI-specific "Extended Properties" and displays the results.

Finally, we must release the created certificate context by P/Invoke to CertFreeCertificateContext().

Conclusion

This short sample demonstrates some of the basic steps needed to access SSL client certificates from an ASP.NET server application. It is also possible to use CAPICOM to access server-side certificates in certificate stores, including the protected private keys in server-side CryptoAPI key containers. In this case, operating system level access permissions will become important, and DACLs may need to be modified to allow certificate access within the context of the ASP.NET application.

ClientCert.aspx source code


Other References:


Michel I. Gallant
neutron@istar.ca