title

Raspberry PI 3


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

表紙

次へ