渡邉一郎日記

趣味かつ独学の成人男性がPython の様々な内容を記事にして発信しております

【nfcpy & PaSoRi】PythonでICカードのIDmを読み取ってみよう

私たちが普段利用しているクレジットカードや交通系ICカードなどには、SONY非接触ICカード技術方式「FeliCa」が採用されています。

また、それらFeliCaカードの情報を読み取る端末として、非接触ICカードリーダー/ライター「PaSoRi(パソリ)」が同じくSONYからリリースされています。

一方で、プログラミング言語Python」には、PaSoRiなどの非接触型デバイスを動作させるためのライブラリ「nfcpy」が用意されています。

この記事では、nfcpyとPaSoRiを使ったICカードIDm(ICチップの固有製造ID)を読み取る方法を紹介します。

使用機器・ソフトウェア

  • PaSoRi:RC-S370
  • Python:version 3.10.5
  • nfcpy:version 1.0.4 → インストール方法後述
  • 7-Zip:version 22.01 → インストール方法後述
  • Zadig:version 2.7 → ダウンロード方法後述
  • WinUSB:version 6.1.7600.16385 → インストール方法後述
  • libusb:version 1.0.26 → ダウンロード方法後述

各ソフトウェアのダウンロード・インストール

各ソフトウェアのダウンロード・インストール方法を説明します。
(※Pythonは省略します。)

nfcpyのインストール

python -m pip install nfcpy

「nfcpy」をインストールしましょう。コマンドプロンプトを起動して、上記コマンドを実行してください。

インストール時に『pipをアップデートしてください』と案内された場合は、下記のコマンドでアップデートしてください。

python -m pip install -U pip

watanabe-ichiro-nikki.hatenablog.com

7-Zipのインストール

7-Zip」をインストールしましょう。

ブラウザで「7-Zip」と検索して公式ページにアクセスしてください。

「7zip」- Google検索結果

公式ページから「7-Zip」をダウンロードしてください。

7-Zip公式ページでの操作

ダウンロードしたファイルを実行して、アカウント制御を許可してください。
※アカウント制御の許可は信頼できるアプリや自己責任で行なってください。

ダウンロードしたファイルを実行 → アカウント制御を許可

アカウント制御を許可すると、7-Zipのセットアップが始まります。「Install」をクリックしてインストールを開始してください。インストールが終了したら「Close」をクリックして閉じます。

7-Zipのインストール画面

これで、7-Zipのインストールは完了です。

Zadigのダウンロード

「Zadig」をダウンロードしましょう。

ブラウザで「Zadig」と検索して公式ページにアクセスしてください。

「Zadig」- Google検索結果

公式ページから「Zadig」をダウンロードしてください。

Zadig公式ページでの操作

これで、Zadigのダウンロードは完了です。ZadigはダウンロードしたEXEファイル自体がアプリ本体なので、インストールという手順はありません。

WinUSBのインストール

「WinUSB」をインストールしましょう。PaSoRi」をPCに接続してから行なってください。

先程ダウンロードした「Zadig」を起動して、アカウント制御を許可してください。
※アカウント制御の許可は信頼できるアプリや自己責任で行なってください。

Zadigの起動

Zadigが起動したら、接続したPaSoRiを選択してください。次に、ドライバーの種類を選択します。
nfcpyを利用する場合は、WinUSBを選択してください。最後に、「Install Driver」をクリックしてインストールを開始します。インストールが終了したら、「Close」をクリックして閉じてください。

WinUSBのインストール

これで、WinUSBのインストールは完了です。

libusbのダウンロードおよび動作環境の構築

「libusb」をダウンロードしましょう。

圧縮ファイルのダウンロード

ブラウザで「libusb」と検索して公式ページにアクセスしてください。

「libusb」- Google検索結果

公式ページ内の「Downloads」にマウスをホバーすると、下にメニューが表示されます。

メニュー内の「Latest Windows Binaries」をクリックすると、ダウンロードが開始されます。

libusb公式ページでの操作

ファイルがダウンロードされたのを確認してください。

ダウンロードしたファイルは圧縮ファイルなので、解凍を行ないます。

ダウンロードした圧縮ファイル

圧縮ファイルの解凍

7-Zip」を起動してください。→【スタート > すべてのアプリ > 7-Zip > 7-Zip File Manager】

起動後、圧縮ファイルをダウンロードしたディレクトリ(フォルダ)を選択してください。

7-Zip起動画面と操作内容

ダウンロードした圧縮ファイルを選択して、「展開」をクリックしてください。

解凍するファイルを選択

展開するときの条件を指定する画面が表示されますが、何も変更せずに「OK」で構いません。

解凍する内容を確認

動作環境の構築

libusbを正常に動作させるために、各フォルダを適切な場所へ移動させます。

圧縮ファイルを解凍すると、フォルダが作成されるのでそれを開いてください。

解凍されたフォルダの確認

エクスプローラーをもう1つ別ウィンドウで開き、「C:\Windows\System32」にアクセスします。

解凍したフォルダの中から、
「libusb-cygwin-x64」
「libusb-MinGW-x64」
「VS2015-x64」
を「C:\Windows\System32」へ移動させてください。

フォルダの移動 Part1

次に、別ウィンドウを「C:\Windows\System32」→「C:\Windows\SysWOW64」へ変更します。

解凍したフォルダの中から、
「libusb-cygwin-Win32」
「libusb-MinGW-Win32」
「VS2015-Win32」
を「C:\Windows\SysWOW64」へ移動させてください。

フォルダの移動 Part2

これで、libusbのダウンロードおよび動作環境の構築は完了です。

IDmの読み取り

ICカードIDmを読み取るためのPythonコードを作成して、実際に読み取りを行なっていきます。

コード作成

import nfc
import binascii

# ICカードの待機
clf = nfc.ContactlessFrontend("usb")
print("カードをかざしてください:")
try:
  tag = clf.connect(rdwr={"on-connect": lambda tag: False})
finally:
  clf.close()

# ICカードのID情報抽出して表示する
if tag.TYPE == "Type3Tag":
  id_info = binascii.hexlify(tag.idm).decode()
elif tag.TYPE == "Type4Tag":
  id_info = binascii.hexlify(tag.identifier).decode()

print("IDm:" + id_info)

上記がICカードIDmを読み取るためのサンプルコードになります。

これを、「read_idm.py」として保存します。
※ファイル名は何でも構いません。

IDmの読み取り

コマンドプロンプトを起動して、「read_idm.py」を実行してください。

コマンドプロンプトからPythonファイルを実行する方法はこちらの記事をご覧ください。

watanabe-ichiro-nikki.hatenablog.com

または、Pythonを起動して先程のコードを実行しても構いません。

IDmの出力結果

これで、ICカードIDmを読み取り出力することができました。

まとめ

この記事では、nfcpyとPaSoRiを使ったICカードIDm(ICチップの固有製造ID)を読み取る方法を紹介しました。

ICカードIDm固有値であるため、その特性から勤怠管理などに利用されることが多く見られます。nfcpyとPaSoRiを使った勤怠管理ツールを作成することも面白そうですね。

追記:Type4Tag について

この記事のコードでは、対象がType4Tag(主にスマホ)の場合、読み取るたびにIDが変化してしまいます。

もしも、Type4Tagを読み取る際に毎回同じID値が欲しい場合は以下のように書き直してください。

try:
  tag = clf.connect(rdwr={"targets": ["212F", "424F"],
                          "on-connect": lambda tag: False})
finally:
  clf.close()

# ICカードのID情報抽出して表示する
if tag.TYPE == "Type3Tag":
  id_info = binascii.hexlify(tag.idm).decode()

print("IDm:" + id_info)

"targets": で指定した ["212F", "424F"] というのは、読み取るときのデータレートを表しています。(デフォルトでは、["106A", "106B", "212F"] )

データレートを指定してあげることで、Type3Tagの情報のみを読み取ることができます。

ただし、このようにデータレートを指定するとクレジットカードやマイナンバーカードなどのID情報を読み取ることはできなくなります。("106A", "106B" に該当するため)

接触ICカードは上記コードで読み取れます。

可能であれば、読み取る対象によって指定できるようにすると良いかと思います。