PCSC sample in Ruby
Here is the PCSC sample in Ruby language I promised in PC/SC sample in different languages.
A PC/SC Wrapper for Ruby also exists at Smart-card communication, straight from ruby.. The latest version is 0.4.11 from 2009. I used an older version 0.3.1 when I worked with this wrapper.
Installation
You first need to install ruby and the other components needed for the compilation of smartcard for Ruby.
apt-get install ruby rake rubygems libopenssl-ruby ruby1.8-dev
Then fetch the archive smartcard-0.4.11.gem
$ sudo gem install echoe
[...]
$ unzip smartcard.zip
$ cd smartcard
$ rake manifest
[...]
$ rake package
(in /home/rousseau/HSLM/smartcard)
Successfully built RubyGem
Name: smartcard
Version: 0.3.1
File: smartcard-0.3.1.gem
Private key not found; gem will not be signed.
Targeting "ruby" platform.
$ rake test
(in /home/rousseau/HSLM/smartcard)
/usr/bin/ruby1.8 extconf.rb
checking for main() in -lpcsclite... yes
checking for wintypes.h... yes
checking for reader.h... yes
checking for winscard.h... yes
checking for pcsclite.h... yes
creating Makefile
[...]
/usr/bin/ruby1.8 -Ilib:ext:bin:test "/var/lib/gems/1.8/gems/rake-0.8.3/lib/rake/rake_test_loader.rb" "test/test_containers.rb" "test/test_smoke.rb"
Loaded suite /var/lib/gems/1.8/gems/rake-0.8.3/lib/rake/rake_test_loader
Started
...
Finished in 0.046223 seconds.
3 tests, 14 assertions, 0 failures, 0 errors
$ rake docs
[...]
Source code
require 'smartcard' context = Smartcard::PCSC::Context.new(Smartcard::PCSC::SCOPE_SYSTEM) readers = context.list_readers nil context.cancel # Use the first reader reader = readers.first # Connect to the card card = Smartcard::PCSC::Card.new(context, reader, Smartcard::PCSC::SHARE_SHARED, Smartcard::PCSC::PROTOCOL_ANY) # Get the protocol to use card_status = card.status # Select applet aid = [0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01] select_apdu = [0x00, 0xA4, 0x04, 0x00, aid.length, aid].flatten send_ioreq = {Smartcard::PCSC::PROTOCOL_T0 => Smartcard::PCSC::IOREQUEST_T0, Smartcard::PCSC::PROTOCOL_T1 => Smartcard::PCSC::IOREQUEST_T1}[card_status[:protocol]] recv_ioreq = Smartcard::PCSC::IoRequest.new response = card.transmit(select_apdu.map {|byte| byte.chr}.join(''), send_ioreq, recv_ioreq) response_str = (0...response.length).map { |i| ' %02x' % response[i].to_i }.join('') puts "Answer: #{response_str}\n" # test APDU test_apdu = [0, 0, 0, 0] response = card.transmit(test_apdu.map {|byte| byte.chr}.join(''), send_ioreq, recv_ioreq) response_str = (0...response.length).map { |i| ' %02x' % response[i].to_i }.join('') puts "Answer: #{response_str}\n" response_str = (0...response.length-2).map { |i| '%c' % response[i].to_i }.join('') puts "Answer: #{response_str}\n" # Deconnect card.disconnect Smartcard::PCSC::DISPOSITION_LEAVE context.release
Output
Answer: 90 00
Answer: 48 65 6c 6c 6f 20 77 6f 72 6c 64 21 90 00
Answer: Hello world!
Conclusion
Nothing more to add. If you are a Ruby user you may be interested by this wrapper.