2020-03-20 「ICカードリーダ Opensc・PCSCD」
ICカードリーダ ACR1251CL-NTTCom が手に入ったのでRaspberry pi 3B で
マイナンバーカード、Suika(PASMO)の読み込みをした。
Felica Lite-S への書き込み。
$ sudo apt install opensc
Openscはパッケージあった。
$ opensc-tool --list-readers
No smart card readers found.
openscだけではリーダーを認識してくれない。
ラズパイマガジンにあったインストールパッケージlibacsccid1を追加すると認識する。
pcscdはopenscインストール時に一緒にインストールされる。
SONY Pasori SC-380は認識しなかった。
$ sudo apt install libacsccid1
$ opensc-tool --list-readers
# Detected readers (pcsc)
Nr. Card Features Name
0 No ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00
”OpenSCでマイナンバーの登録情報を確認してみた”でマイナンバーカードを置いて、コマンド実行すると読み込まれる。
$ pkcs15-tool --dump
Using reader with a card: ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00
PKCS#15 Card [JPKI]:
Version : 0
Serial number : 00000000
Manufacturer ID: JPKI
Flags :
PIN [User Authentication PIN]
Object Flags : [0x12], modifiable
ID : 01
;;;
;;;
証明書も読み込まれた。
$ pkcs15-tool --read-certificate 1
Using reader with a card: ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00
-----BEGIN CERTIFICATE-----
MxXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
SlADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDzZXIgYXV0aGVu
;;;
;;;
;;;
7jUS6fTvbQ8E2HDdu+Zy+RNhsVGU+HmvKUqXqfffffffffffffffffffevTjtPNp
ddkdkdkdkdkddddddddddddddddddddddddddddddddddddCw41nGsAWZls+tQ==
-----END CERTIFICATE-----
Suicaコマンドはラズパイマガジンにあったコマンドで読めた。
$ opensc-tool -s ffca000000
Using reader with a card: ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00
Sending: FF CA 00 00 00
Received (SW1=0x90, SW2=0x00):
xx xx xx xx xx xx 3E 21 ......>!
$ opensc-tool -s FF00000006060000030000
Using reader with a card: ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00x
Sending: FF 00 00 00 06 06 00 00 03 00 00
Received (SW1=0x90, SW2=0x00):
12 01 xx xx xx xx xx xx 3E 21 04 01 4B 02 4F 49 ........>!..K.OI
93 FF ..
$ opensc-tool -s FF000000101006xxxxxxxxxxxx3e21010f09018000
Using reader with a card: ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00
Sending: FF 00 00 00 10 10 06 xx xx xx xx xx xx 3E 21 01 0F 09 01 80 00
Received (SW1=0x90, SW2=0x00):
1D 07 xx xx xx xx xx xx 3E 21 00 00 01 xx xx xx ........>!......
00 xx xx xx xx 00 00 03 00 00 08 17 00 ....g........
PYTHONライブラリは、
sudo apt install python3-pyscard
でインストールすると使える。
ラズパイ2018-10月号のPYTHONプログラムのカードリード部分を使用するとSUICA,PASMOの残高が読める。
スマホのおサイフケータイアプリの残高照会と同じ金額のこと。
参考資料”RC-S380 を用いたFeliCa Lite-Sへの書き込み”と”ラズパイマガジン 2018.10月号”を真似してやってみた。
$ nano card-write-read.py
----
#!/usr/bin/env python3
# -*- coding: utf-8
import sys
import smartcard.System
from smartcard.scard import *
from smartcard.util import toHexString
def main():
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
hresult, readers = SCardListReaders (hcontext, [])
if hresult < 0 or len(readers) == 0:
print("No Card Reader!!")
return
reader_status = [(readers[0], SCARD_STATE_UNAWARE)]
hresult, newstates = SCardGetStatusChange (hcontext, 0, reader_status)
while True:
reader, eventstate, atr = newstates[0]
if eventstate & SCARD_STATE_PRESENT:
hresult, readers = SCardListReaders(hcontext, [])
print('PCSC Readers:', readers)
hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, readers[0], SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
print('Connected with active protocol', dwActiveProtocol)
felica_cmd = [ 0x00 ] # FELICA_POLLING
felica_cmd.extend([0x88, 0xB4]) # felica lite
felica_cmd.append(0x00)
felica_cmd.append(0x00)
felica_cmd_length = len(felica_cmd)
apdu_cmd = [0XFF, 0x00, 0x00, 0x00]
apdu_cmd.append(felica_cmd_length + 1)
apdu_cmd.append(felica_cmd_length + 1)
apdu_cmd.extend(felica_cmd)
print("=================")
print("==== Polling ====")
sdat = 'Send: '
for n in apdu_cmd:
sdat = sdat + '%02X'%n + ' '
print(sdat)
hresult, response = SCardTransmit( hcard, dwActiveProtocol, apdu_cmd)
sdat = 'Retun Status=%d : ' % hresult
for n in response:
sdat = sdat + '%02X'%n + ' '
print(sdat)
idm = response[2:10]
pmm = response[11:19]
index = 1
felica_cmd = [ 0x08 ] # FELICA_WRITE_WITHOUT_ENCRYPTION
felica_cmd.extend(idm)
felica_cmd.append(0x01)
felica_cmd.extend([0x09, 0x00])
felica_cmd.append(0x01)
felica_cmd.append(0x80)
felica_cmd.append(index) # index
felica_cmd.extend([ord('2'),ord('0'),ord('2'),ord('0'),ord('-'),ord('0'),ord('3'),ord(' '),ord('T'),ord('e'),ord('s'),ord('t'),ord('C'),ord('a'),ord('r'),ord('d')] )
felica_cmd_length = len(felica_cmd)
apdu_cmd = [0XFF, 0x00, 0x00, 0x00]
apdu_cmd.append(felica_cmd_length + 1)
apdu_cmd.append(felica_cmd_length + 1)
apdu_cmd.extend(felica_cmd)
print("=================")
print("== Write Block ==")
sdat = 'Send: '
for n in apdu_cmd:
sdat = sdat + '%02X'%n + ' '
print(sdat)
hresult, response = SCardTransmit( hcard, dwActiveProtocol, apdu_cmd)
sdat = 'Retun Status=%d : ' % hresult
for n in response:
sdat = sdat + '%02X'%n + ' '
print(sdat)
print("================")
print("== Read Block ==")
felica_cmd = [0x06 ] # FELICA_READ_WITHOUT_ENCRYPTION
felica_cmd.extend(idm)
felica_cmd.append(0x01)
felica_cmd.extend([0x09, 0x00])
felica_cmd.append(0x01)
felica_cmd.append(0x80)
felica_cmd.append(index)
felica_cmd_length = len(felica_cmd)
apdu_cmd = [0XFF, 0x00, 0x00, 0x00]
apdu_cmd.append(felica_cmd_length + 1)
apdu_cmd.append(felica_cmd_length + 1)
apdu_cmd.extend(felica_cmd)
sdat = 'Send: '
for n in apdu_cmd:
sdat = sdat + '%02X'%n + ' '
print(sdat)
hresult, response = SCardTransmit( hcard, dwActiveProtocol, apdu_cmd)
sdat = 'Retun Status=%d : ' % hresult
for n in response:
sdat = sdat + '%02X'%n + ' '
print(sdat)
sdat = 'Block No.%3d : ' % index
sch = ''
for n in response[13:29]:
if ( n < 32 or n >= 127 ):
sch += '.'
else:
sch += chr(n)
sdat = sdat + '%02X'%n + ' '
print(sdat + " | \"" + sch + "\"")
break
if eventstate & SCARD_STATE_EMPTY:
print("Empty Card")
hresult, newstates = SCardGetStatusChange (hcontext, INFINITE, newstates)
if __name__ == '__main__':
main()
----
$ ./card-write-read.py
PCSC Readers: ['ACS ACR1251 CL Reader [ACR1251 CL Reader PICC] 00 00']
Connected with active protocol 2
=================
==== Polling ====
Send: FF 00 00 00 06 06 00 88 B4 00 00
Retun Status=0 : 12 01 01 2E 48 C4 BE CD xx BF 00 F1 00 00 00 01 43 00 90 00
=================
== Write Block ==
Send: FF 00 00 00 20 20 08 01 2E 48 C4 BE CD xx BF 01 09 00 01 80 01 32 30 32 30 2D 30 33 20 54 65 73 74 43 61 72 64
Retun Status=0 : 0C 09 01 2E 48 C4 BE CD xx BF 00 00 90 00
================
== Read Block ==
Send: FF 00 00 00 10 10 06 01 2E 48 C4 BE CD xx BF 01 09 00 01 80 01
Retun Status=0 : 1D 07 01 2E 48 C4 BE CD xx BF 00 00 01 32 30 32 30 2D 30 33 20 54 65 73 74 43 61 72 64 90 00
Block No. 1 : 32 30 32 30 2D 30 33 20 54 65 73 74 43 61 72 64 | "2020-03 TestCard"
[参考資料]
https://techmedia-think.hatenablog.com/entry/2017/10/21/150246
OpenSCでマイナンバーの登録情報を確認してみた
ラズパイマガジン 2018.10月号 p-115 ~ 120
ラズパイ電子工作 お手軽レシピ集 Part2 ZeroでSuikaの残高を調べる
https://pyscard.sourceforge.io/epydoc/smartcard.scard.scard-module.html
scard reference (Python PCSC wrapper)
https://tomosoft.jp/design/?p=9632
RC-S380 を用いたFeliCa Lite-Sへの書き込み
FeliCa Lite-S ユーザーズマニュアル Version 1.3