Skip to content

Instantly share code, notes, and snippets.

@zmajstor
Created August 23, 2014 12:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmajstor/af52f7b0f1c5f9ab2b98 to your computer and use it in GitHub Desktop.
Save zmajstor/af52f7b0f1c5f9ab2b98 to your computer and use it in GitHub Desktop.
SmartCard adapter using smartcard gem with demo
# http://www.rdoc.info/github/costan/smartcard/master/Smartcard
require 'smartcard'
class SmartCardAdapter
# scope of the smart-card connection; valid values are :system, :user, and :terminal
# (see the SCARD_SCOPE_ constants in the PC/SC API)
def connect(scope = :system)
@context = Smartcard::PCSC::Context.new(scope)
end
def readers
@context.readers
end
def disconnect
@card.disconnect if @card
@context.release if @context
end
def select_card_in_the_first_reader
@card = @context.card(@context.readers.first) if @context && @context.readers.any?
end
def send_APDU_to_current_card(bytes_array)
# send_data is a string containing the APDU bytes to be sent to the card
send_data = bytes_array.pack('C*')
response = @card.transmit(send_data)
# hex(response[-2, 2])
hex(response)
end
def dump_current_card_info
puts "Dumping Card state and data:"
puts "card protocol: #{@card.protocol}"
puts "card sharing mode: #{@card.sharing_mode}"
info = @card.info
# puts "\ncard info: #{info}"
puts "card ATR (hex): #{hex(info[:atr])}"
puts "card state: #{info[:state].to_a.join(' ')}"
end
private
def hex(input)
input.unpack('C*').map{ |e| e.to_s(16).upcase }.join(' ')
end
end
require_relative 'smart_card_adapter'
begin # demo
print "Searching for Smart Card..."
adapter = SmartCardAdapter.new
readers = adapter.readers if adapter.connect
abort("No Smart Card readers found") if adapter.nil? || readers.empty?
puts " found: #{readers}"
print "connecting to the first reader..."
card = adapter.select_card_in_the_first_reader
puts " connected!" if card
adapter.dump_current_card_info
apdu_bytes = [0x80, 0xC0, 0x02, 0xA1]
puts "response: #{adapter.send_APDU_to_current_card(apdu_bytes)}"
puts "\n"
rescue Smartcard::PCSC::Exception => e
puts "Ooops: #{e}"
ensure
adapter.disconnect if adapter
end
# how to format proper APDU bytes string?
# http://web.archive.org/web/20090630004017/http://cheef.ru/docs/HowTo/APDU.info
# http://www.wrankl.de/SCTables/SCTables.html
# apdu_bytes = [0x00, 0xA4, 0x04, 0x00, 0x00]
# apdu_bytes = [0xFF, 0xCA, 0x00, 0x00, 0x00] # get UID
# apdu_bytes = [0xAF, 0x03, 0x16, 0x78] # BH
# apdu_bytes = [0x20, 0x00, 0x82, 0x04, 0x01, 0x02, 0x03, 0x04, 0x00]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment