OpenSCでSuicaの利用履歴を読む方法と履歴データのフォーマット解析

#はじめに
OpenSCを使ってSuicaから利用履歴を読み出します。
・読み出すためのAPDUコマンドを説明します。
・読み出した履歴データの見方を説明します。

#環境
- OS=Windows10
- カードリーダー=PaSoRi RC-S380
- ICカード= Suica（Felica）

#OpenSCとは
- https://github.com/OpenSC/OpenSC/wiki
- https://qiita.com/gebo/items/eb76d2b83041cdb47ec3

#さっそくやってみる
- コマンドプロンプトを立ち上げる。
- opensc-tool.exe のフォルダに移動して以下コマンド実行する。
- opensc-tool.exe -s FF:A4:00:01:02:0F:09
- opensc-tool.exe -s FF:B0:00:00:00
- Received の次の行に出た値（**16 01 00 04 24 99 E3 59 E3 5E 71 0B 00 1B 08 00**）が利用履歴です。

```console:サンプル-最新の利用履歴を読む
C:\Program Files\OpenSC Project\OpenSC\tools>opensc-tool.exe -s FF:A4:00:01:02:0F:09
Using reader with a card: Sony FeliCa Port/PaSoRi 3.0 0
Sending: FF A4 00 01 02 0F 09
Received (SW1=0x90, SW2=0x00)

C:\Program Files\OpenSC Project\OpenSC\tools>opensc-tool.exe -s FF:B0:00:00:00
Using reader with a card: Sony FeliCa Port/PaSoRi 3.0 0
Sending: FF B0 00 00 00
Received (SW1=0x90, SW2=0x00):
16 01 00 04 24 99 E3 59 E3 5E 71 0B 00 1B 08 00
```

#opensc-tool.exeとは
- ICカードリーダーと通信するツール。
- 詳細は[コチラ](https://qiita.com/gebo/items/eb76d2b83041cdb47ec3)を参照。

#opensc-tool.exe -s FF:A4:00:01:02:0F:09
- FF:A4:00:01:02:0F:09 がカードに送信するAPDUコマンド。
- Suicaの利用履歴サービスを操作する指定コマンド(Select File)
- 利用履歴サービスコードは　0x090f
- サービスコードの指定はリトルエンディアン。(つまり、コマンドでは0f-09と指定する）
- 応答　SW1=0x90, SW2=0x00　で正常終了という意味。

##Select File APDUコマンド
| byte no|項目名|指定値|説明|
|:--|:--|:--|:--|
|0|CLA|FF|命令クラス　FF固定|
|1|INS|A4|Select File|
|2|P1|00|エリア数　00固定|
|3|P2|01|サービス数　01固定|
|4|Le|02|データサイズ　02固定|
|5|Data|0F|Selectするサービス|
|6|Data|09|Selectするサービス|

#opensc-tool.exe -s FF:B0:00:00:00
- FF:B0:00:00:00 がカードに送信するAPDUコマンド
- ?APDU?という人は、下でリンク貼っているEternalWindowsというサイトを読むといいかと思います。
- 利用履歴の1件目を取得するAPDUコマンド(Read Binary)
- **P2(ブロックNo)に00～指定することで履歴のx件目を取得することができる**
- 応答　SW1=0x90, SW2=0x00　で正常終了で、その次の行で履歴データが取れます
- 履歴データは16byte

##Read Binary APDUコマンド
| byte no|項目名|指定値|説明|
|:--|:--|:--|:--|
|0|CLA|FF|命令クラス　FF固定|
|1|INS|B0|Read Binary|
|2|P1|00|Block開始位置指定　00固定|
|3|P2|00|Blockリスト指定　**ブロックNo**|
|4|Le|00|00固定|

###補足
FF:B0:00:01:00　とすると履歴の2件目、
FF:B0:00:02:00　とすると履歴の3件目が取れます。
※何件までとれるかはカードによって違う？のか、正確な情報が見つけられませんでした。（テストに使ったカードは13件まで取れた）

#履歴データの形式
さて、Read Binaryで取得したデータの形式はどうなっているのでしょうか。
**16 01 00 04 24 99 E3 59 E3 5E 71 0B 00 1B 08 00**

##SUICA利用履歴ブロックフォーマット
2018/4/25に乃木坂から代々木上原まで乗って、残高が￥2929だったってことですね。

| byte no|項目名|取れた値|値の意味|
|:--|:--|:--|:--|
|0|端末種|16|改札機|
|1|処理|01|運賃支払|
|2|支払種別|00|現金/なし|
|3|入出場種|04|入場/定期出場|
|4-5|日付|24:99|2018/4/25|
|6|入線区|E3|乃木坂|
|7|入駅順|59|乃木坂|
|8|出線区|E3|代々木上原|
|9|出駅順|5E|代々木上原|
|10-11|残高|71:0B|￥2929|
|12-14|連番|0B:00:1B||
|15|地域コード|00||

###端末種、処理
それぞれ1byteのコードで表現されています。
[コチラ](https://ja.osdn.net/projects/felicalib/wiki/suica)のサイト参照ください。

###支払種別、入出場種
それぞれ1byteのコードで表現されています。
[コチラ](http://jennychan.web.fc2.com/format/suica.html)のサイトを参照ください。

###日杖
2byteで表現されています。
先頭から7ビットが年、４ビットが月、残り５ビットが日。
0x24:0x99 をビットにすると、
0010-0100-1001-1001 となりますので、以下のようになります。

- 7bit=0010-010　→　10進数に変換する　→　18(年)
- 4bit=0-100　→　10進数に変換する　→　4(月)
- 5bit=1-1001　→　10進数に変換する　→　25(日)

###入選区、入駅順、出線区、出駅順
区と順で駅コードとなります。以下のcsvから求まります。
[駅コードデータベースStationCode.csv](http://wp.utopiat.net/wp-content/uploads/2017/08/StationCode.csv)

###残高
リトルエンディアンで設定されています。
簡単に求めたければ以下サイトから。
[残高計算（16進法とリトルエンディアンの変換）](http://web.save-editor.com/tool/wse_hex.html)

###連番
？詳細不明？

###地域コード
1byteのコードで表現されています。
[コチラ](http://jennychan.web.fc2.com/format/suica.html)のサイトを参照ください。

#最後に
履歴は結構簡単に読み出せます（PINの入力とかも不要）。NFCが付いたAndroid端末を使って履歴情報を読み出すアプリもたくさんあります。

#あわせて参照すべきサイト
- 履歴データのフォーマットが説明されているサイト
	- https://ja.osdn.net/projects/felicalib/wiki/suica
	- https://wp.utopiat.net/2017/08/305/
- [EternalWindows スマートカード](http://eternalwindows.jp/security/scard/scard00.html)
- SDK for NFC ユーザーズマニュアル PC/SC編
	- ⇒[SDK for NFC Starter Kitダウンロード（無償）](https://www.sony.co.jp/Products/felica/business/products/ICS-D004.html)の中に入っています。