In this article, you will learn how to use smart card certificates in your .NET application. It covers most of the steps to achieve this from creating the certificate to selecting it in the smart card and using it to perform a PKCS11 signature with the security classes of .NET. In order to apply those concepts, you will need a PKI (Public Key) smart card. Those devices are nowadays very affordable and you can get one with a reader from vendors like Gemalto for less than 80$ (I'm not working anymore with this company...).
This article doesn't demonstrate what you can do with a PKI infrastructure but will show you how easy it is (when you find out how to do it...) to use a smart card PKI device with .NET and C#. Those who have some experience with PKCS#11 library will understand what I mean!
Using a PKI Smart Card as a CSP Provider
You won't find a lot of code in this article because most of it is done by the framework itself, however I have concentrated in this article on many tricks that I have learned while using a smart card to license the database of our enterprise application.
The first step is to generate the PFX certificate which is the format that most smart card utilities use to install certificate on the card. This is a relatively easy process when you know the steps. The important thing is that the private key must be exported. After few searches, I found a short but very useful page that gives the solution and you can get it here.
You will need 3 utilities:
- makecert.exe to create the certificate and its private key
- cert2spc.exe to convert the certificate file .cer to the .spc format (Software Publisher Certificate)
- pvkimprt.exe which will combine the .spc file and the .pvk into the desired PFX file (PKCS#12 format)
are available with Microsoft SDKs and can be found in the "Program Files\Microsoft SDKs\Windows
is an Office utility that can be downloaded from Microsoft WEB here
In a DOS shell, you'll have to type the following commands after setting the correct path.
makecert -r -n "CN=CodeProject" -b 01/01/2000 -e 01/01/2099
-eku 126.96.36.199.188.8.131.52.3 -sv smartcert.pvk smartcert.cer
cert2spc smartcert.cer smartcert.spc
pvkimprt -pfx smartcert.spc smartcert.pvk
This is going to generate 2 files that we need to use, the smartcert.cer contains only the public key (although it is possible to include the private key) and the smartcard.pfx is a full RSA key pair that is protected by password because the private key is the most sensible part of a certificate. When generation is done, you will be prompted to give passwords.
Microsoft Next Generation Smart Card Framework
I'm not going to describe here this framework as you can find a lot of good articles on the WEB that do that. What you need to know is that this framework saves you a lot of code and burden to integrate PKI smart cards in a .NET application. Before the BaseCSP and minidriver architecture, you would have needed to use PKCS#11 and write a lot of interop code. Now the only thing you need to do is to use the proper CSP (Crypto Service Provider) for your smart card.
When you install the drivers of the smart card, the vendor will provide the necessary libraries that integrate within this framework. However even with the CSP architecture, there are 2 approaches depending on how recent the implementation of the vendor is. The first CSP architecture would be required from the vendor to write a complete CSP provider, while with the new BaseCSP architecture, the vendor would have written only a minidriver that seats below the BaseCSP.
Microsoft Smart Card CSP Architecture
The next thing you need to do is to install the PFX certificate in the smart card. Any smart card vendor will provide a simple utility to do that. We're not talking here about certificate management which is far beyond that topic, but a simple Windows or WEB utility to upload the certificate to the card and this should take a PFX file as this is the standard for exchanging certificates. When you import the PFX file, you should be prompted for the certificate password that you entered when creating the certificate and also for a container name. The container name is what we will use to select the certificate.
Creating a CSP with the Smart Card Certificate
This is where the code begins! The first thing you need to do is to find out which CSP your card is using. Like I mentioned before, if your card is supported by the new BaseCSP then you will refer to the standard Smartcard CSP (Microsoft Base Smart Card Crypto Provider), if your card is of an older generation you may need to use the vendor specific CSP, for example the Gemplus GemSafe card would use "Gemplus GemSAFE Card CSP v1.0".
Those values can be found in the registry at the following place: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults\Provider.
Now that we know what CSP to use, let's get down to the code. The following lines create a
CspParameters class that links you to the Smart card certificate. There are 2 key parameters in order to select the right certificate, those are the CSP name and the container name. The last parameter is the PIN code that you need to enter when using the certificate from card, basically a 4 PIN digit like the one of your SIM card or bank card.
[__strong__]CspParameters csp =
"Microsoft Base Smart Card Crypto Provider",
Now that we have "connected" the CSP to the smart card, we can use the certificate to sign some data. Of course, the purpose of signing is that you verify the signature. The principle of a digital signature is that you sign some data with your private key and the recipient of your message will verify the signature using the public key that you can distribute.
I'm not going to go deep inside the signature mechanism as there are already a lot of articles on CodeProject regarding this subject and a lot more on the WEB. I just want to point out that a certificate is a TRUST asset, to be trusted it needs to have been issued by a trusted party, that's where company like Verisign or RSA come into place. In fact, it all depends on the level of trust you require. If you want to use the certificate for your personal usage, then you can use those utilities to create self-signed certificate that you can distribute to your friends.
In order to verify, we need the public key of our certificate. An easy way to get it is to create a
RSACryptoServiceProvider using the
CspParameters we just created, then simply export the public key to an XML format with the method
ToXmlString(false). Then in the program that verifies the signature, you just create the key of the
RSACryptoServiceProvider with the method
FromXmlString(xmlKey) and use this CSP instance to verify the signature.
The complete code provided sign some data with the smart certificate and verifies the signature using the XML representation of the public key.
In a real secure environment, you would distribute the .CER file for example that contains only the public key and install it on the recipient certificate store.
Accessing the smart card certificate from a Windows Service or a WCF service running under Windows 7 or Windows Server 2008
I recently accessed the certificate on the card through a WCF service hosted with IIS7 on Windows 7 and I faced a singular issue. When calling the service, I got a message telling that the Smart card manager was not running. Accessing the card from ths application was perfectly working so I guessed that something was blocking the card when the code was executed by the IIS process.
I found out on some post that an SCard API called by the .NET Framework to access the card is failing with an
E_ACCESS_DENIED error. An interesting post explains that thanks to the UAC and extended security in Windows 7 and Windows Server 2008 the old smart card API now fails when called from a NT service or a WCF service hosted with IIS (I haven't tried with one hosted in Windows service but the outcome is predictable).
The solution is to change the access right with the authorization API to grant access to the smart card resource manager to everyone! The only problem with that solution is that it needs to be applied every time the machine is restarted. A simple solution is to create a registry string under the key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run.
Included is a short piece of code in C I found on the MSDN and which does the job.
Then there is the case of Windows Server 2008...
The authorization code will work on Windows 2008 ONLY if the machine is in a domain. So far, I could find any explanation (even asking on a MSDN forum), but my empiric experience shows that if you run this code on a server 2008 which is not in a domain, the call to
GetNamedSecurityInfo returns 5 (Access Denied) and you cannot give the access to the SC resource manager.
Of course, this little code is not only useful if you need to access a smart card certificate but in any situation where you need to access a smart card resource from a windows service or a WEB service.
Points of Interest
After reading this article, you should be able to use a smart card certificate in a .NET application using the latest CSP framework of Microsoft. If you want to go further and find out what you can do with PKI, I suggest that you browse the CodeProject Cryptography & Security articles where you will find a lot of interesting subjects!
- 13th August, 2011: Initial version
- 5th October, 2011: Article updated