Click here to Skip to main content
13,763,464 members
Click here to Skip to main content
Add your own
alternative version


332 bookmarked
Posted 5 Dec 2006
Licenced CPOL

A Smart Card Framework for .NET

, 15 May 2015
Rate this:
Please Sign up or sign in to vote.
Describes a framework to use the PCSC Smart Card API with .NET.


 On the 18th of February 2013 this article passed the 500000 views mark. Thanks to all the visitors! That's a small figure for the internet but I'm amazed that this small library that was written almost 10 years ago with the beta  of .Net 1.0 is so popular. Another thing that puzzled me is that after 10 years there is still no support for Smart card in the .NET Framework (Except the Crypto service provider of course). Anyway I'll do some re-factoring to improve it because the current architecture is a bit rusty and no so object oriented! 

The .NET Framework has been introduced in 2002, and the version 3.0 has just been released in November. So far, Microsoft hasn't included Smart Card classes in .NET, and if you want to develop a Smart Card aware application, you have to develop your own classes. Fortunately, it is much easier to reuse existing code in .NET than with Java. In Windows, if you need to use Smart Card, you just need to use the PC/SC API in your program. This API comes in C functions or COM objects that wrap the PC/SC functions. The .NET Framework offers two types of interoperabilities with the legacy code: the COM interoperability, and the P/Invoke feature for native code interoperability. I strongly advise to use the Native code that allows more interaction, in particular a better event support. 


This article demonstrates how to use the interoperability features of .NET and use them to write a simple framework to use a Smart Card in your applications. A Smart Card is a small embedded device that receives commands through a card reader using the PC/SC Win32 API. If you want to use this API, you will need a Smart Card reader to use a Smart Card such as a SIM card.

A Simple Smart Card Framework

The SC framework I'm going to describe is composed of an interface to communicate with the Smart Card, a few classes to wrap the different parameters of a Smart Card command, and the implementation classes depending on the interop mode we are using.

The Smart Card interface provides a simple access to a Smart Card for .NET programs. We will see later how to implement this interface using both the interoperability techniques.

spublic interface ICard
    string[] ListReaders();
    void Connect(string Reader, SHARE ShareMode, 
                 PROTOCOL PreferredProtocols);
    void Disconnect(DISCONNECT Disposition);
    APDUResponse Transmit(APDUCommand ApduCmd);
    void BeginTransaction();
    void EndTransaction(DISCONNECT Disposition);

The classes APDUCommand and APDUResponse are used to send the command and get the response from the card. SHARE, PROTOCOL, and DISCONNECT are constants used by PC/SC.

public class APDUCommand
    public APDUCommand(byte bCla, byte bIns, 
           byte bP1, byte bP2, byte[] baData, byte bLe);
    public void Update(APDUParam apduParam);
    public override string ToString();
    public byte    Class;
    public byte    Ins;
    public byte    P1;
    public byte    P2;
    public byte[]  Data;
    public byte    Le;

public class APDUResponse
    public APDUResponse(byte[] baData);
    public byte[]    Data;
    public byte    SW1;
    public byte    SW2;
    public ushort    Status;
    public override string ToString();

Adding Card Events Support

When a card is inserted in the reader or removed, PC/SC allows you to handle those events. So I added a card event support to this framework based on the event model of .NET. The class CardBase, which inherits from the interface ICard, implements support for two events, CardInserted and CardRemoved. The mechanism of detection is implemented in the derived class that implements ICard. So far I only implemented this support in CardNative. If you want to support the event in your application program, you just need to implement the CardInsertedEventHandler and the CardRemovedEventHandler.

abstract public class CardBase : ICard
    public event CardInsertedEventHandler OnCardInserted = null;
    public event CardRemovedEventHandler OnCardRemoved = null;
    abstract public string[] ListReaders();
    abstract public void Connect(string Reader, 
             SHARE ShareMode, PROTOCOL PreferredProtocols);
    abstract public void Disconnect(DISCONNECT Disposition);
    abstract public APDUResponse Transmit(APDUCommand ApduCmd);
    abstract public void BeginTransaction();
    abstract public void EndTransaction(DISCONNECT Disposition);
    public void StartCardEvents(string Reader);
    public void StopCardEvents();
    abstract protected void RunCardDetection();
    protected void CardInserted();
    protected void CardRemoved();

I developed two implementations of the interface ICard. One is using COM interoperability, and the other using native interoperability with P/Invoke. Both implementations behave the same way. In addition, I ported the P/Invoke implementation for the Compact Framework so it is possible to develop Smart Card applications for the Pocket PC.

CardCOM: A COM Interoperability Implementation Class

COM interoperability is the simplest way to reuse legacy code in .NET framework. All versions of Visual Studio .NET provide very good support for COM. You just need to add a reference to the COM object you need to import, and it generates a wrapper DLL and all the necessary classes to use your COM interfaces. Basically, you don't have to write any code. However, your COM components must respect a few rules, specially regarding the parameters used in the methods. The different interfaces of the PC/SC COM components were written long before .NET existed, and some of the interfaces are not totally compliant with COM interoperability. This is why I had to develop my own COM interface to get the list of readers. For the most important interface, ISCard and the interfaces it uses the import went fine.

interface ISCardDatabaseEx : IDispatch{
    [id(1), helpstring("method ListReaders")] 
       HRESULT ListReaders([out,retval] VARIANT* ppReaders);

The COM component I developed replaces the ISCardDatabase interface, and only implements one of its methods: ListReaders. In the Microsoft implementation, the return parameter is a SAFEARRAY of BSTR, which unfortunately .NET is unable to import properly. The right way to do it is to use a VARIANT* that contains the SAFEARRAY of BSTR. Then, .NET will generate a wrapper method that returns an object that you just have to cast into a string[]. Using a COM object in .NET is as simple as adding a reference to this object in your code. Visual Studio will then generate a wrapper class that you directly use in your code. The following extract illustrates this.

using SCARDSSPLib;    // use the SCard COM object

/// <summary>
/// Default constructor
/// </summary>
public CardCOM()
    // Create the SCard object
    m_itfCard = new CSCardClass();

public override void Connect(string Reader, 
       SHARE ShareMode, PROTOCOL PreferredProtocols)
    // Calls AttachReader to connect to the card
        (SCARD_SHARE_MODES) ShareMode, 
        (SCARD_PROTOCOLS) PreferredProtocols);

The ISCardDatabase interface is provided in a DLL that must be registered with Regsvr32.

CardNative: A Native Interoperability Implementation Class using P/Invoke

The Platform Invoke mechanism (P/Invoke) is a very powerful mechanism that gives total access to the Win32 platform API. The .NET framework provides a complete set of classes that you can use to achieve every marshaling operation necessary to call Win32 functions from .NET. Those classes are defined in the System.Runtime.InteropServices assembly that you just need to import in your program. The P/Invoke mechanism, even if it is a bit complex, is far more convenient than the JNI mechanism of Java. All the atomic types like int, byte, long, etc... are automatically marshaled by the compiler itself. The byte[] is also automatically marshaled as an input or output parameter. When you have to deal with more complex parameters like strings, structures, or a pointer to a structure, .NET provides a set of marshaling classes that can be used as attributes or objects in your program when marshaling parameters. To develop the CardNative class, I didn't have to develop any extra code to use the PC/SC API, all the code is in the source file CardNative.cs. When you want to use a Win32 API C function, you need to declare the function in your class using the interoperability attributes provided by the System.Runtime.InteropServices assembly. Once you have declared the function, you can just use it as any C# method in your class. The following code sample illustrates this mechanism.

[DllImport("winscard.dll", SetLastError=true)]
internal static extern    int    SCardTransmit(UInt32 hCard,
    [In] ref SCard_IO_Request pioSendPci,
    byte[] pbSendBuffer,
    UInt32 cbSendLength,
    IntPtr pioRecvPci,
    [Out] byte[] pbRecvBuffer,
    out UInt32 pcbRecvLength

public override APDUResponse Transmit(APDUCommand ApduCmd)
    uint    RecvLength = (uint) (ApduCmd.Le + APDUResponse.SW_LENGTH);
    byte[]    ApduBuffer = null;
    byte[]    ApduResponse = new byte[ApduCmd.Le + APDUResponse.SW_LENGTH];
    SCard_IO_Request    ioRequest = new SCard_IO_Request();
    ioRequest.m_dwProtocol = m_nProtocol;
    ioRequest.m_cbPciLength = 8;

    // Build the command APDU

    if (ApduCmd.Data == null)
        ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 
                    ((ApduCmd.Le != 0) ? 1 : 0)];

        if (ApduCmd.Le != 0)
            ApduBuffer[4] = (byte) ApduCmd.Le;
        ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 + 
        for (int nI = 0; nI < ApduCmd.Data.Length; nI++)
            ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] = 
        ApduBuffer[APDUCommand.APDU_MIN_LENGTH] = 
                 (byte) ApduCmd.Data.Length;

    ApduBuffer[0] = ApduCmd.Class;
    ApduBuffer[1] = ApduCmd.Ins;
    ApduBuffer[2] = ApduCmd.P1;
    ApduBuffer[3] = ApduCmd.P2;

    m_nLastError = SCardTransmit(m_hCard, 
        ref ioRequest, 
        (uint) ApduBuffer.Length, 
        IntPtr.Zero, ApduResponse, out RecvLength); 

    if (m_nLastError != 0)
        string msg = "SCardTransmit error: " + m_nLastError;
        throw new Exception(msg);

    byte[] ApduData = new byte[RecvLength];

    for (int nI = 0; nI < RecvLength; nI++)
        ApduData[nI] = ApduResponse[nI];
    return new APDUResponse(ApduData);

Demo Application

The Smart Card API is very easy to use. However, if you want to write a Smart Card application, you must know the commands to send to the card to perform operations such as selecting files, verifying PINs, or reading data. Those commands are called APDU commands, and are described in the specification of the Smart Card you want to access. The purpose of this article is not to explain how to use a Smart Card, but to give you a simple C# API to play with any Smart Card you'd want.

Most people have a GSM phone so if you have a Smart Card reader on your PC (some laptops come with an embedded Smart Card reader), you can use the little demo program to play with your SIM card. This simple program presents the PIN (if your PIN is activated), selects the phone number file, and reads the 10 first records of this file. Everything you will get is in binary format like it is stored in the card. If your PIN is activated, you must uncomment the line that verifies the PIN in my code. The PIN value is entered in binary. If your PIN is 1234, you must enter 31323334 and pad with FF bytes until the PIN length is 8.

In the second part of this article, I will present a more advanced framework to write Smart Card applications. This framework will use the classes I described in this article, and will make it easier writing Smart Card applications.

WCS Smart card service

In a recent article I have added a WCF service to expose the ICard interface implemented by the NativeCard class. Doing that I have improved a little the exception support in the original code.

For the moment only 32 bits is supported and the card events are not yet mapped to the WCF service.  

Points of Interest 

In this first part, we have seen two methods to use legacy code with .NET. This is one of the very powerful features of .NET that makes it the ideal managed framework to develop applications on the Windows platform. This Smart Card framework can be very useful if you want to access a Smart Card application in your .NET code. Of course, VB.NET users can use this framework as well.

However, this set of class still requires that you write dedicated code to access the card using the APDU command which is not the most interesting code to write. In the second part of this article, I will give you an XML framework that allows to write Smart Card applications with minimum code, using XML declarations.


  • 5 Mar 2007 - Added a support for the ATR and other attributes, SCardGetAttrib function of PC/SC
  • 16 Aug 2011 - Added project updated for Visual Studio 2010
  • 26 Aug 2011 - Added 64 bit project for Visual Studio 2008, 2010
  • 29 Janv 2013 - Exception support improvement, added a WCF service that wraps ICard  
  • 20 Feb 2013 - 500000 views mark. 
  • 15 May 2015 - Corrected few issues while adding some support for Mifare Classic cards. Please get the code form Github:


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Architect Connect In Private
Singapore Singapore
Software Architect, COM, .NET and Smartcard based security specialist.

I've been working in the software industry since I graduated in Electrical and Electronics Engineering. I chose software because I preferred digital to analog.

I started to program with 6802 machine code and evolved to the current .NET technologies... that was a long way.

For more than 20 years I have always worked in technical positions as I simply like to get my hands dirty and crack my brain when things don't go right!

After 12 years in the smart card industry I can claim a strong knowledge in security solutions based on those really small computers!
I've been back into business to design the licensing system for the enterprise solution for Consistel using a .NET smart card (yes they can run .NET CLR!)

I'm currently designing a micro-payment solution using the NXP DESFire EV1 with the ACSO6 SAM of ACS. I can then add a full proficient expertise on those systems and NFC payments.
This technology being under strict NDA by NXP I cannot publish any related article about it, however I can provide professional consulting for it.

You can contact me for professional matter by using the forum or via my LinkedIn profile.

You may also be interested in...


Comments and Discussions

GeneralRe: read only iccid or imsi Pin
Member 825806915-Mar-13 1:38
memberMember 825806915-Mar-13 1:38 
AnswerRe: read only iccid or imsi Pin
orouit21-Mar-13 5:42
professionalorouit21-Mar-13 5:42 
Questionaide pour lire sms via pcsc c++ php msdos Pin
stefba23-Jan-13 6:18
memberstefba23-Jan-13 6:18 
AnswerRe: aide pour lire sms via pcsc c++ php msdos Pin
orouit19-Feb-13 3:51
professionalorouit19-Feb-13 3:51 
QuestionUID smart card with contact Pin
Member 967495629-Dec-12 0:30
memberMember 967495629-Dec-12 0:30 
AnswerRe: UID smart card with contact Pin
Member 96749564-Jan-13 5:27
memberMember 96749564-Jan-13 5:27 
GeneralRe: UID smart card with contact Pin
orouit4-Jan-13 22:42
professionalorouit4-Jan-13 22:42 
QuestionConfusion regarding your project "ApduExchange" Pin
Member 970467122-Dec-12 12:04
memberMember 970467122-Dec-12 12:04 
Dear Oliver,

thanks a lot for your interesting application. I am working in the smart card industry for more than 10 years as a project manager and product manager for personalization systems.
So, the smart card world is fully clear to me, however my knowledge on C# is still limited:

Analysing your code, I found it strange (most likely due to my limited C# knowledge) that in the "ApduExchange" project, there is no class "Program.cs" containing the "Main" method. Instead you have all code in "MainForm.cs", i.e. the method "Mainform()", the code generated by Windosw Form Designer, the method "InitializeComponent()", the "Main()" method and finally all event handlers.

If I generate a Windows Form Application using Visual Studio 2010 (Express), I get the the Form (e.g. "Form1.cs"), the Designer generated code (Form1.Designer.cs") and the "Program.cs" seperately, whereas the "Main()" method is located in Program.cs.

Could you please explain, what is behind you approach having all components in "MainForm.cs" rather than seperating it as it is done when generating a new Windows Form application?

Many thanks and MERRY CHRISTMAS to you.

Best regards,
AnswerRe: Confusion regarding your project "ApduExchange" Pin
orouit24-Dec-12 2:11
professionalorouit24-Dec-12 2:11 
AnswerRe: Confusion regarding your project "ApduExchange" Pin
Member 970467124-Dec-12 13:11
memberMember 970467124-Dec-12 13:11 
QuestionGSM SIM cards Pin
Member 898564912-Dec-12 21:50
memberMember 898564912-Dec-12 21:50 
AnswerRe: GSM SIM cards Pin
orouit14-Dec-12 3:35
professionalorouit14-Dec-12 3:35 
QuestionI have two identical smart card readers (OMNIKEY) and only the first reader to install on my system (Windows 7 - 64 bit) detects events OnCardInserted / Removed Pin
Member 967495612-Dec-12 6:05
memberMember 967495612-Dec-12 6:05 
AnswerRe: I have two identical smart card readers (OMNIKEY) and only the first reader to install on my system (Windows 7 - 64 bit) detects events OnCardInserted / Removed Pin
Member 967495612-Dec-12 7:52
memberMember 967495612-Dec-12 7:52 
GeneralRe: I have two identical smart card readers (OMNIKEY) and only the first reader to install on my system (Windows 7 - 64 bit) detects events OnCardInserted / Removed Pin
orouit14-Dec-12 3:28
professionalorouit14-Dec-12 3:28 
Questionhow to store data into the smart card Pin
Jin00710-Dec-12 16:07
memberJin00710-Dec-12 16:07 
AnswerRe: how to store data into the smart card Pin
orouit10-Dec-12 23:27
professionalorouit10-Dec-12 23:27 
QuestionSmart card detection Pin
rejectkosta1-Dec-12 7:03
memberrejectkosta1-Dec-12 7:03 
AnswerRe: Smart card detection Pin
orouit1-Dec-12 17:00
professionalorouit1-Dec-12 17:00 
GeneralRe: Smart card detection Pin
rejectkosta2-Dec-12 1:19
memberrejectkosta2-Dec-12 1:19 
GeneralRe: Smart card detection Pin
orouit5-Dec-12 5:21
professionalorouit5-Dec-12 5:21 
GeneralRe: Smart card detection Pin
Sam_Yem19-Apr-13 4:08
professionalSam_Yem19-Apr-13 4:08 
GeneralRe: Smart card detection Pin
orouit21-Apr-13 18:08
professionalorouit21-Apr-13 18:08 
GeneralRe: Smart card detection Pin
Sam_Yem25-Apr-13 9:07
professionalSam_Yem25-Apr-13 9:07 
GeneralRe: Smart card detection Pin
orouit4-May-13 19:29
professionalorouit4-May-13 19:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.181112.3 | Last Updated 15 May 2015
Article Copyright 2006 by orouit
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid