目的
交通機関などで使われるようなICカードの中身をpythonを使って自宅で閲覧するための検証をします。
とりあえず、読み取るだけまでを目指し、なるべくシンプルなコードで試そうと思います。
環境
- Windows10 64bit
- python3.7(Anaconda3)
- PaSoRi(RC-S380)
方針
pythonにはnfcpyというnfcデバイスの制御ができる、素晴らしいライブラリがあります。今回はこのnfcpyを使用します。
以下のnfcpyの説明サイトで詳しく書かれていますので、これを参考に進めたいと思います。
https://nfcpy.readthedocs.io/en/latest/topics/get-started.html
簡単に言うと、次のような順番で実施します。
- Zadigというツールを使いWinUSBをインストールする。
- libusbをインストールする。
- pythonでコーディングする。
WinUSBとはMicrosoftが提供するUSBドライバらしく、おそらく、PaSoRiなどのリーダのIO制御に必要なのかと思います。そして、ZadigはそのWinUSBを簡単にインストールできるGUIベースのツールのようです。
libusbはUSBデバイスへアクセスするためのCのライブラリで、おそらくnfcpyを使う前提として必要なのだと思います。
ということで、まずはWinUSBとlibusbを準備した上で、pythonのnfcpyを使ってコーディングをしていきたいと思います。
Step1 : WinUSBのインストール
以下のZadigのサイトからZadigの最新版をダウンロードします。今回はzadig-2.4をダウンロードしました。
https://zadig.akeo.ie
zadig-2.4.exeをダウンロードして任意の場所に保存した後、右クリック から 管理者として実行を選択します。
すると、GUIが開くので、以下のようにOptions > List All Devicesにチェックを入れます。

次に、PCのUSB端子にPaSoRi(RC-S380)を接続し、下図のようにプルダウンメニューからNFC Port/PaSoRi 100 USBを選択します。

そして、Driverのところで、WinUSB(v6.1.7600.16385)を選択し、Install Driverをボタンを押します。下図は一旦インストールした際に撮ったスクショのため、Reinstall Driverになってますが、初回はInstall Driverになっているはずです。

Install Driverをクリックすると、インストールが始まりますので、完了するまで待ちます。以上でWinUSBのインストールは完了です。
Step2 : libusbのインストール
以下のサイトからlibusbをダウンロードします。ページのDownloads > Lates Windows Binariesを選択すると、ダウンロードが開始され、7zの拡張子の圧縮ファイルが落ちてきます。
https://libusb.info/
ダウンロードしたファイルを任意の場所へ保存したら、7zipを使って解凍します。なお、7zipをPCにインストールしていない場合は以下から入手できます。
https://www.7-zip.org/download.html
解凍して生成されたフォルダの中から以下の2つのファイルを指定の場所にコピーします。この作業を忘れるとPaSoRiは動きませんので、注意してください。
- MS64dll\libusb-1.0.dllを C:\Windows\System32 へコピーする。
- MS32\dll\libusb-1.0.dll を C:\Windows\SysWOW64 へコピーする。
以上でlibusbのインストールは完了です。
Step3 : Pythonによる実装
まず、Anaconda promptを立ち上げてnfcpyをインストールします。
$ pip install nfcpy
次に、PaSoRiの上にICカードを載せます。
そして、以下のコードを実行します。
import nfc #接続定義 clf = nfc.ContactlessFrontend('usb') print(clf) #タグの取得 tag = clf.connect(rdwr={'on-connect': lambda tag: False}) #結果表示 print(tag) print(dir(tag))
#====Result=========== SONY RC-S380/P on usb:002:001 Type3Tag 'FeliCa Standard (RC-S???)' ID=xxxxxx PMM=xxxxxx SYS=xxxxxx ['IC_CODE_MAP', 'NDEF', 'TYPE', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_authenticated', '_clf', '_format', '_is_present', '_ndef', '_nfcid', '_product', '_target', 'authenticate', 'clf', 'dump', 'dump_service', 'format', 'identifier', 'idm', 'is_authenticated', 'is_present', 'ndef', 'pmm', 'polling', 'product', 'protect', 'read_from_ndef_service', 'read_without_encryption', 'request_response', 'request_service', 'request_system_code', 'search_service_code', 'send_cmd_recv_rsp', 'sys', 'target', 'type', 'write_to_ndef_service', 'write_without_encryption']
ICに用意されているタグが簡単にわかりました。
あとは、tag.dumpすると、実際のデータを見ることができます。(途中割愛しています)
tag.dump()
#---Result 'System 0003 (Suica)', 'Area 00 ' Cyclic Service 36: write with key & read w/o key..., ' 0000: 16 01 00 ... |........D.......|',
データを見ることはできましたが、データの意味まで理解するためには、そもそもどんな形でデータが入っているかの予備知識があったり、暗号化されていないことが前提となりそうです。
結果
python nfcpyを使うと、初心者でもデータの中身まで簡単に表示できました。
ただし、中身の意味を知ろうとした場合はICカードがどう運用されているのかの予備知識も必要そう。平文ベタ打ちなら何かしらはわかるかも。
以上