This are few notes to getting starting interfacing Java application with smart card. In particular, this step are what you need to read personal data on an Italian Healty Card by Java code.
First to all, you need to install, if not already, the pcsc-lite daemon:
[root@raspi ~]# yum install -y pcsc-lite pcsc-lite-devel pcsc-tools
The reader I used is an Athena ASEDrive IIIe USB. you need to install the driver:
Download the driver from http://www.athena-scs.com/support/software-driver-downloads#asedrive
Extract in a directory
Build
To build the driver you needed the kernel header and libusb-devel package, if can install them with: [root@raspi ~]# yum install -y libusb-devel |
[root@raspi ~]# wget http://www.athena-scs.com/docs/reader-drivers/asedriveiiie-usb-3-7-tar.bz2 --2013-06-20 22:58:14-- http://www.athena-scs.com/docs/reader-drivers/asedriveiiie-usb-3-7-tar.bz2 Risoluzione di www.athena-scs.com (www.athena-scs.com)... 50.61.225.43 Connessione a www.athena-scs.com (www.athena-scs.com)|50.61.225.43|:80... connesso. Richiesta HTTP inviata, in attesa di risposta... 200 OK Lunghezza: 33062 (32K) [application/octet-stream] Salvataggio in: "asedriveiiie-usb-3-7-tar.bz2" 100%[=======================================================================================================================================================================================>] 33.062 92,1KB/s in 0,4s 2013-06-20 22:58:15 (92,1 KB/s) - "asedriveiiie-usb-3-7-tar.bz2" salvato [33062/33062] [root@raspi ~]# tar xjvf asedriveiiie-usb-3-7-tar.bz2 asedriveiiie-usb-3.7/ asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/ asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/ asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/Linux/ asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/ asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/ asedriveiiie-usb-3.7/Makefile asedriveiiie-usb-3.7/50-pcscd-asedriveiiie.rules asedriveiiie-usb-3.7/usb.c asedriveiiie-usb-3.7/ifdhandler.c asedriveiiie-usb-3.7/InitCardParams.c asedriveiiie-usb-3.7/ReaderCommands.c asedriveiiie-usb-3.7/CommandTypes.c asedriveiiie-usb-3.7/Ase.h asedriveiiie-usb-3.7/atr.c asedriveiiie-usb-3.7/T1Protocol.c asedriveiiie-usb-3.7/Makefile.inc asedriveiiie-usb-3.7/ChangeLog asedriveiiie-usb-3.7/README asedriveiiie-usb-3.7/T1Protocol.h asedriveiiie-usb-3.7/MemoryCards.h asedriveiiie-usb-3.7/MemoryCards.c asedriveiiie-usb-3.7/LinuxDefines.h asedriveiiie-usb-3.7/LICENSE asedriveiiie-usb-3.7/DriverIO.c asedriveiiie-usb-3.7/configure asedriveiiie-usb-3.7/atr.h asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/PkgInfo asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/Info.plist asedriveiiie-usb-3.7/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/InfoPlist.strings [root@raspi ~]# cd asedriveiiie-usb-3.7/ [root@raspi asedriveiiie-usb-3.7]# ./configure [root@raspi asedriveiiie-usb-3.7]# make gcc -o libASEDriveIIIe-USB.so usb.c atr.c DriverIO.c CommandTypes.c ReaderCommands.c T1Protocol.c MemoryCards.c InitCardParams.c ifdhandler.c -fPIC -D_REENTRANT -DIFDHANDLERv2 -Wall -I. -pthread -I/usr/include/PCSC -lpcsclite -lusb -shared InitCardParams.c: In function ‘MatchReaderParams’: InitCardParams.c:52:9: warning: variable ‘F’ set but not used [-Wunused-but-set-variable] ifdhandler.c: In function ‘closeDriver’: ifdhandler.c:30:9: warning: variable ‘retVal’ set but not used [-Wunused-but-set-variable] [root@raspi asedriveiiie-usb-3.7]# make install install -c -d "//usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents" install -c -m 0644 ifd-ASEDriveIIIe-USB.bundle/Contents/Info.plist ifd-ASEDriveIIIe-USB.bundle/Contents/PkgInfo "//usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents" install -c -d "//usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj" install -c -m 0644 ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj/InfoPlist.strings "//usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents/Resources/English.lproj" install -c -d "//usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents/Linux" install -c -m 0755 libASEDriveIIIe-USB.so "//usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents/Linux" install -c -m 0644 50-pcscd-asedriveiiie.rules /etc/udev/rules.d/. [root@raspi asedriveiiie-usb-3.7]#
Now run pcsc deamon in foreground just to see some informative log:
[root@raspi asedriveiiie-usb-3.7]# pcscd -f -d 00000000 debuglog.c:269:DebugLogSetLevel() debug level=debug 00004254 configfile.l:245:DBGetReaderListDir() Parsing conf directory: /etc/reader.conf.d 00002498 configfile.l:298:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin 00004571 configfile.l:257:DBGetReaderListDir() Skipping non regular file: . 00002167 configfile.l:257:DBGetReaderListDir() Skipping non regular file: .. 00000276 pcscdaemon.c:525:main() pcsc-lite 1.8.7 daemon ready. 00022326 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001 00003756 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001 00003800 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x0424, PID: 0x9512, path: /dev/bus/usb/001/002 00003659 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x0424, PID: 0xEC00, path: /dev/bus/usb/001/003 00003832 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x0424, PID: 0x9512, path: /dev/bus/usb/001/002 00003737 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/004 00003834 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x04F3, PID: 0x0216, path: /dev/bus/usb/001/005 00003836 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/004 00003692 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1C4F, PID: 0x0016, path: /dev/bus/usb/001/006 00003693 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1C4F, PID: 0x0016, path: /dev/bus/usb/001/006 00003968 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/004 00003751 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/007 00003868 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/004 00003677 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x0424, PID: 0x9512, path: /dev/bus/usb/001/002 04086407 hotplug_libudev.c:260:get_driver() Looking for a driver for VID: 0x0DC3, PID: 0x0802, path: /dev/bus/usb/001/009 00002260 hotplug_libudev.c:312:HPAddDevice() Adding USB device: AseIIIeUSB 00002214 readerfactory.c:978:RFInitializeReader() Attempting startup of AseIIIeUSB 00 00 using /usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents/Linux/libASEDriveIIIe-USB.so 00032344 dyn_unix.c:81:DYN_GetAddress() IFDHCreateChannelByName: /usr/lib/pcsc/drivers/ifd-ASEDriveIIIe-USB.bundle/Contents/Linux/libASEDriveIIIe-USB.so: undefined symbol: IFDHCreateChannelByName 00002717 readerfactory.c:836:RFBindFunctions() Loading IFD Handler 2.0 00084851 readerfactory.c:327:RFAddReader() Using the pcscd polling thread
Insert the smart card into reader:
99999999 eventhandler.c:372:EHStatusHandlerThread() powerState: POWER_STATE_POWERED 00002218 eventhandler.c:387:EHStatusHandlerThread() Card inserted into AseIIIeUSB 00 00 00002378 Card ATR: 3B DF 18 00 81 31 FE 7D 00 6B 15 0C 01 81 01 11 01 43 4E 53 10 31 80 E8 00403402 eventhandler.c:446:EHStatusHandlerThread() powerState: POWER_STATE_UNPOWERED
In a new windows compile and run this simple Java programm:
import java.util.List; import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardTerminal; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; import javax.smartcardio.TerminalFactory; import javax.xml.bind.DatatypeConverter; public class ReadCard { public static void main(String[] argv) throws Exception { // show the list of available terminals TerminalFactory factory = TerminalFactory.getDefault(); List<CardTerminal> terminals = factory.terminals().list(); System.out.println("Terminals: " + terminals); // get just the first terminal CardTerminal terminal = terminals.get(0); // establish a connection with the card Card card = terminal.connect("T=1"); System.out.println("card: " + card); CardChannel channel = card.getBasicChannel(); byte[] apdu = DatatypeConverter.parseHexBinary("00A40800063F001100110200"); ResponseAPDU r = channel.transmit(new CommandAPDU(apdu)); System.out.println("response: " + new String(r.getBytes())); apdu = DatatypeConverter.parseHexBinary("00B0000080"); r = channel.transmit(new CommandAPDU(apdu)); System.out.println("response: " + new String(r.getBytes())); apdu = DatatypeConverter.parseHexBinary("00B0008080"); r = channel.transmit(new CommandAPDU(apdu)); System.out.println("response: " + new String(r.getBytes())); apdu = DatatypeConverter.parseHexBinary("00B0010080"); r = channel.transmit(new CommandAPDU(apdu)); System.out.println("response: " + new String(r.getBytes())); apdu = DatatypeConverter.parseHexBinary("00B0018010"); r = channel.transmit(new CommandAPDU(apdu)); System.out.println("response: " + new String(r.getBytes())); // disconnect card.disconnect(false); } }
This is the result:
[dometec@raspi ~]$ javac ReadCard.java [dometec@raspi ~]$ java ReadCard Terminals: [PC/SC terminal AseIIIeUSB 00 00] card: PC/SC card in AseIIIeUSB 00 00, protocol T=1, state OK response: o;������ f����f���▒��������������������������� response: 00006B04603..........XXXX..HIDE PERSONAL DATA :).................