The CSharp PC/SC Wrapper for .NET

The. NET Framework class library does not support smart cards in version 4.0. Therefore, in this book a CSharp PC / SC wrapper was developed, which WinSCard the main Windows API functions embedded in the WinSCard class. In addition to WinSCard class provides the class PCSCReader a high-level PC / SC API.

Low-Level-API
The WinSCard class, in the GS.SCard namespace, encapsulates the most commonly used WinSCard API functions in the form of a class. Functions not yet implemented in  the WinSCard API can be added to the open source library if needed. All constants for the WinSCard API from the winscard.h header file, as well as the error codes from SCardErr.h are declared in several enumerations (namespace GS.SCard.Const and GS.SCard.ReturnCodes).

High-Level-API
The PCSCReader class, from the GS.PCSC namespace, offers the Connect(), ActivateCard(), Exchange() and Disconnect().methods. All of these methods are partially overloaded, making it easier to program a PC/SC-compliant reader.

 

icon_zip.gif CSharpPCSC API, Documentation and Examples


CSharp PC/SC Examples

The C # programming examples can be compiled and tested either with  Smart Card Magic.NET   or Microsoft Visual Studio C # 2012 Express Edition or SharpDevelop. The creation of programs in Smart Card Magic.NET is presented in Chapter 7.6.2. The in Chapter 8 presented generic helper classes CmdApdu, RespApdu, ByteArray, HexEncoding, HexFormatting, HexUtil, MifareClassicKeys, MifareClassicUtil, TripleDESCrypto and Rng are used in the following examples again.

 icon_zip.gif PC/SC Reader Smart Card Magic.NET Script Examples

namespace GS.PCSCExample
{
  public class PCSCDESFireISO7816APDUs
  {
    static MainForm script;
    PCSCReader reader;
    
    public PCSCDESFireISO7816APDUs()
    {
      reader = new PCSCReader();
    }
    
    
    public static void Main(MainForm script, string[] args)
    {
      PCSCDESFireISO7816APDUs readerScript = new PCSCDESFireISO7816APDUs();
      PCSCDESFireISO7816APDUs.script = script;
      readerScript.Run();
    }        
    
    public void Run()
    {
      try
      {   
          reader.Connect();
        
          reader.ActivateCard();
            
          //----------------------------------------------------------------------
          //                       Select Master File
          //----------------------------------------------------------------------
          // CLA = 0x00, INS = 0xA4, P1 = 0x00, P2 = 0x00, Lc = 2 (data length),
          // Data = 0x3F 00, Le -
          byte[] selectMF = new byte[]{ 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };  
             
          script.TraceWriteLine("    Select Master File: FID = 0x3F 00");
          reader.Exchange( selectMF, 0x9000);

          //----------------------------------------------------------------------
          //                       Select Application
          //----------------------------------------------------------------------                
          CmdApdu selectApplication = new CmdApdu();
          selectApplication.CLA = 0x00;   
          selectApplication.INS = 0xA4;  
          selectApplication.P1 = 0x04;    
          selectApplication.P2 = 0x00;
          selectApplication.Data = new byte[] {0x11,0x22,0x33,0x44,
                                               0x55,0x66,0x77,0x88};
  
          script.TraceWriteLine(" Select Application: AID = 0x1122334455667788");
          reader.Exchange(selectApplication, 0x9000);

          //----------------------------------------------------------------------
          //                       Select File
          //----------------------------------------------------------------------  
          CmdApdu selectFile = new CmdApdu();
          selectApplication.CLA = 0x00;   
          selectApplication.INS = 0xA4;   
          selectApplication.P1 = 0x00;    
          selectApplication.P2 = 0x00;
          selectApplication.Data = HexEncoding.GetBytes("00 01");
  
          script.TraceWriteLine("    Select File: FID = 0x0001");
          reader.Exchange(selectApplication, 0x9000);

          //----------------------------------------------------------------------
          //                       Update Binary
          //----------------------------------------------------------------------  
          // CLA = 0x00, INS = 0xD6, P1 = 0x00, P2 = 0x00, Lc = 8 (data length), 
          // Data = 0x31 32 33 34 35 36 37 38, Le -
          script.TraceWriteLine("    Update Binary:");
          reader.Exchange("00 D6 00 00 # (31 32 33 34 35 36 37 38)", 0x9000);

          //----------------------------------------------------------------------
          //                       Update Binary
          //----------------------------------------------------------------------  
          // CLA = 0x00, INS = 0xD6, P1 = 0x00, P2 = 0x00, Lc = 11 (data length), 
          // data = 0x48 65 6C 6C 6F 20 57 6F 72 6C 64 , Le -
          script.TraceWriteLine("    Update Binary:");
          reader.Exchange("00 D6 00 08 # (\"Hello World\")", 0x9000);   

          //----------------------------------------------------------------------
          //                       Read Binary
          //----------------------------------------------------------------------  
          // CLA = 0x00, INS = 0xB0, P1 = 0x00, P2 = 0x00 (offset), Lc = -, 
          // data = - , Le = 0x00
          script.TraceWriteLine("    Read Binary:");
          RespApdu respApdu2 = reader.Exchange("00 B0 00 00 00", 0x9000);                

          //----------------------------------------------------------------------
          //                       Read Binary
          //---------------------------------------------------------------------- 
          // CLA = 0x00, INS = 0xB0, P1 = 0x00, P2 = 0x08 (offset), Lc = -, 
          // data = - , Le = 0x00                
          script.TraceWriteLine("    Read Binary:");
          RespApdu respApdu1 = reader.Exchange("00 B0 00 08 10");
        
          if(respApdu1.SW1SW2 == 0x9000 && respApdu1.ReaderStatus == 0x00)
          {
            string cardText = System.Text.Encoding.ASCII.GetString(respApdu1.Data);
            Console.WriteLine("Card Text: " + cardText);
          }

        }
        catch (WinSCardException ex)
        {
          Console.WriteLine( ex.WinSCardFunctionName + " Error 0x" + 
                             ex.Status.ToString( "X08" ) + ": " + ex.Message );
        }
        catch (Exception ex)
        {

            Console.WriteLine( ex.Message );
        }
        finally
        {
            reader.Disconnect();
        }
     }
  }
}