WindowsでOpenSCを使う（2.カードのIDm確認編）

# はじめに
[WindowsでOpenSCを使う（1.準備編）](https://qiita.com/erik_tnk/items/7d40b02be3bb13f2c3af)の続きです。

# 使用するツール
- コマンドプロンプト
- opensc-tool.exe（[WindowsでOpenSCを使う（1.準備編）](https://qiita.com/erik_tnk/items/7d40b02be3bb13f2c3af)参照）
- カードリーダー：PaSoRi RC-S380
- ICカード=Felica

# ICカードが認識されるか確認しよう
使用するコマンドは`opensc-tool.exe -a`です。
このコマンドを使用することにより、ATRを取得することができます。
ATR(Answer To Reset)とは、カードが電気的に活性化した際にカードから送られる初期応答情報です。ATRを取得することで、ICカードが認識されていると判断できます。


①コマンドプロンプトを立ち上げる
②`cd`でopensc-tool.exeのあるパスに移動する
![2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409907/e2e5aaf8-b411-9ceb-2d86-016034cd48a9.png)
③`opensc-tool.exe -a`を実行する。
![2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409907/81e345ab-0038-a487-6992-8748299f3334.png)
↑青色部分がATR値です。
カードが認識されない場合は青色部分に`Failed to connect to card: Card not present`と表示されます。その上の`Using reader with a card: Sony FeliCa Port/PaSoRi 3.0 0`は接続しているカードリーダーの情報です。

# カードのIDmを取得しよう
いよいよカードのIDmを取得します。
ここで使用するコマンドは`opensc-tool.exe -s`です。
`opensc-tool.exe -s`を使用して、APDUコマンドをカードに送信します。ここでいきなり登場したAPDUコマンドについては後述します。
ICカードを認識した時と同じ要領で`opensc-tool -s FF:CA:00:00:00`コマンドを送信すると、画像のような応答が返ってきます。
![2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409907/effe3277-e75e-d96f-0413-f54b5a6abe4e.png)

緑色部分がカードのIDm(UID)です。今回はFelicaを使用して、8byteのIDｍが取得されました。
ピンク部分はカードのIDm(UID)を文字列に直したものです。無視して大丈夫です。
`Received (SW1=0x90, SW2=0x00)`はカードから返ってきたレスポンスで、正常終了を意味します。

# ADPUコマンドとは
APDU(Application Protocol Data Unit)という、カードに対する命令とそれに付随するデータです。
コマンドを受信したカードは応答としてレスポンスを返し、アプリケーションはレスポンスを確認して、コマンドが成功したかどうかを判断します。

>カードに送るコマンドがカード毎に異なる設計になっている場合、 アプリケーションはカードの数だけコマンドを理解する必要が生じ、 互換性の維持が難しくなります。 こうした問題を解消し、カードの設計に共通の規約を設ける意味で、 ISO 7816という国際規約が制定されています。 この規約は、カードの性質を15のパートに区分けして規定し、 その中のISO 7816-4/8/9がカードに送るべきコマンドの構造を規定しています。 したがって、このコマンドを理解しておくことで、 ISO 7816準拠の各カードを共通のコードで取り扱うことができるようになります。 
>EternalWindows
[スマートカード / コマンドとレスポンスより引用](http://eternalwindows.jp/security/scard/scard07.html))

今回使用したコマンドは引用元のISO 7816準拠の各カードを共通のコードを使用しています。
ISO 7816におけるコマンドの基本のフォーマットはこれ。

<table border="1">
    <tr>
        <th colspan="4" style="text-align:center">ヘッダー</th>
    </tr>
    <tr>
        <td>CLA</td><td>INS</td><td>P1</td><td>P2</td>
    </tr>
</table>

そして今回使用したコマンドのフォーマットはこれ。

<table border="1">
    <tr>
        <th colspan="4" style="text-align:center">ヘッダー</th><th>ボディ</th>
    </tr>
    <tr>
        <td>CLA</td><td>INS</td><td>P1</td><td>P2</td><td>Le</td>
    </tr>
</table>

ヘッダー部の4項目がコマンドに必須で、ボディ部のデータはオプションです。
今回はオプションのLeがついている形ですね。ほかにもパターンがありますが割愛します。
簡単に項目と意味を説明すると下記の表のようになります。

<table border="1">
    <tr>
        <th>項目名</th><th>サイズ</th><th>説明</th>
    </tr>
    <tr>
        <td>CLA</td><td>1byte</td><td>クラスバイトのこと。</td>
    </tr>
    <tr>
        <td>INS</td><td>1byte</td><td>コマンドが行うべき命令の値</td>
    </tr>
    <tr>
        <td>P1</td><td>1byte</td><td>コマンドのパラメータ。値はINSに依存。</td>
    </tr>
    <tr>
        <td>P2</td><td>1byte</td><td>コマンドのパラメータ。値はINSに依存。</td>
    </tr>
    <tr>
        <td>Le</td><td>1byte or 3byte</td><td>レスポンスの最高サイズ</td>
    </tr>
</table>


# 今回使用したコマンドの解説
`FF:CA:00:00:00` GetDataコマンド = IDm(UID)問い合わせ

<table border="1">
    <tr>
        <th>byte No</th><th>項目名</th><th>指定値</th><th>説明</th>
    </tr>
    <tr>
        <td>0</td><td>CLA</td><td>FF</td><td>命令クラス FF固定</td>
    </tr>
    <tr>
        <td>1</td><td>INS</td><td>CA</td><td>GET DATAコマンド</td>
    </tr>
    <tr>
        <td>2</td><td>P1</td><td>00</td><td>今回パラメータ不要なので00固定</td>
    </tr>
    <tr>
        <td>3</td><td>P2</td><td>00</td><td>今回パラメータ不要なので00固定</td>
    </tr>
    <tr>
        <td>4</td><td>Le</td><td>00</td><td>データサイズ。何のデータサイズだろう。よくわからないときは00でいいと思う。</td>
    </tr>
</table>

これでICカードのIDmが読み取れます。FelicaもTypeA、TypeBもいけるみたいです。

後から確認してみたら、LeはなくてもIDm取得できました...
よく考えたら00だから何も指定してないのと同義ですよね。

ちなみに`opensc-tool -s FF:CA:00:00:00`の`:`を略して
`opensc-tool -s FFCA000000`と送信してもOKです！

# 今後調べていきたいこと

- コマンドの調べ方
 - CLAに`FF`を設定すれば命令を意味することになる...ほかのCLAはどこに書いてあるの？
 - GetDataはOpenSCだと`CA`だけど、参考サイト様では`0xca`だったので同じ意味だと最初わかっていなかったり...あんまり根本的に理解できてないので
- OpenSC使わないでアプリでカード認識していくやり方など


# 参考
[WindowsでOpenSCを使ってカードのIDmを確認する方法](https://qiita.com/gebo/items/eb76d2b83041cdb47ec3)
[EternalWindows
スマートカード / コマンドとレスポンス](http://eternalwindows.jp/security/scard/scard07.html)

# 関連ページ
[WindowsでOpenSCを使う（1.準備編）](https://qiita.com/erik_tnk/items/7d40b02be3bb13f2c3af)
[WindowsでOpenSCを使う（3.MIFARE Classicブロックデータ読み出し編①）](https://qiita.com/erik_tnk/items/9eb14d689870004596bb)