マイナンバーカード検証#1 - まえおき

#はじめに
今さらですが~~全く普及しない~~マイナンバーカードの検証をしました。
マイナンバーカードの中の公開鍵を取り出したり、署名したり、署名検証したりです。
書き始めたら長くなったので何本かに分けます。

本検証をするにあたり参考にしたサイト
- [OpenSC](https://github.com/OpenSC/OpenSC)
- [OpenSC JPKIカードドライバ](https://www.jnsa.org/seminar/pki-day/2017/data/170419_hamano.pdf)

####注意事項
- マイナンバーカードのPINを何度か間違えるとロックがかかって使えなくなります。
- ロックを解除するには役所に行って申請書を書く必要があります。
- 本サイトを見て同じようなことをやってみる場合は[このあたりの説明](https://www.jpki.go.jp/procedure/password.html)を一読し、めんどくさいリスクがあることを理解したえでお願いします。

#目次
[１．実行環境](https://qiita.com/gebo/items/6a334b5453817a587683#%EF%BC%91%E5%AE%9F%E8%A1%8C%E7%92%B0%E5%A2%83)
[２．まえおき](https://qiita.com/gebo/items/6a334b5453817a587683#%EF%BC%92%E3%81%BE%E3%81%88%E3%81%8A%E3%81%8D)
[２－１．ICカードとお話する方法](https://qiita.com/gebo/items/6a334b5453817a587683#%EF%BC%92%EF%BC%91ic%E3%82%AB%E3%83%BC%E3%83%89%E3%81%A8%E3%81%8A%E8%A9%B1%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
[２－２．マイナンバーカードについて](https://qiita.com/gebo/items/6a334b5453817a587683#%EF%BC%92%EF%BC%92%E3%83%9E%E3%82%A4%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC%E3%82%AB%E3%83%BC%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
[２－３．公的個人認証APについて](https://qiita.com/gebo/items/6a334b5453817a587683#%EF%BC%92%EF%BC%93%E5%85%AC%E7%9A%84%E5%80%8B%E4%BA%BA%E8%AA%8D%E8%A8%BCap%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
[２－４．APDUコマンドについて](https://qiita.com/gebo/items/6a334b5453817a587683#%EF%BC%92%EF%BC%94apdu%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)

#１．実行環境
- Windows10 1803
- .Net Framework 4.6.1
- [パソリ-PaSoRi RC-S380](https://www.sony.co.jp/Products/felica/consumer/products/RC-S380.html)
- マイナンバーカード

検証ツール
- [OpenSSL](https://www.openssl.org/)
- [Git Hub - Lib/DemoApp](https://github.com/gebogebogebo/JPKIReader)
 
#２．まえおき
本題に入る前に まえおき をいろいろと。

##２－１．ICカードとお話する方法
WindowsでICカードとのデータ通信はICカードリーダを通して行います。PCの機種によってはスマホのようにICカードリーダが本体に内蔵されているものもありますので、そういう場合はICカードリーダは不要です。
ここではICカードリーダーはパソリを使っていますが、PC/SCという標準仕様で通信するので他のICカードリーダも使えるかと思います。

実際にICカードのデータを処理するWindowsアプリケーションはC#のデスクトップアプリケーションを対象とします。C#では基本的には.Net Frameworkを使いますが、ICカードと通信するPC/SC関連のAPIが.Net Frameworkには見当たりません。そのため、WindowsAPIを直接C#から利用します。これが面倒なんですけど決められた手順で呼び出せばいいだけです。

利用するWindowsAPIは以下の通りです。
winscard.dll
- SCardEstablishContext　⇒　SCard系APIの初期処理
- SCardListReadersW　⇒　ICカードリーダの情報をGETする
- SCardConnectW　⇒　ICカードリーダーのハンドルをGETする
- SCardTransmit　⇒　ICカードにコマンド(`APDU`)を送信して応答をGETする
- SCardDisconnect　⇒　ICカードリーダーと切断する
- SCardReleaseContext　⇒　SCard系APIの終了処理
そのほか、引数を準備するとか戻り値を評価するとか必要です。とにかくめんどくさいので [ラッパ関数](https://github.com/gebogebogebo/JPKIReader/blob/master/Source/JPKIReader/JPKIReader/SCard/SCardAPI.cs) を作ってあとは気にしないことにします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/252291/20e95b34-ce0f-1e94-a2ce-ea117a38ab86.png)

 
##２－２．マイナンバーカードについて
マイナンバーカードといえば12桁のマイナンバーです。ですが、ここではマイナンバーを取り扱うわけではなく、カードの中に入っている証明書、秘密鍵、公開鍵にアクセスします。
マイナンバーカードとは何かという説明は[ここ](https://ja.wikipedia.org/wiki/%E5%80%8B%E4%BA%BA%E7%95%AA%E5%8F%B7%E3%82%AB%E3%83%BC%E3%83%89)とか[ここ](http://www.soumu.go.jp/kojinbango_card/03.html)を参照いただくとして、ポイントは

- ISO/IEC 14443 **Type B**
- アプリが入っている
	- 券面アプリケーション（券面AP）
	- **公的個人認証サービスによる電子証明書アプリケーション（公的個人認証AP/JPKI-AP）**
	- 券面事項入力補助アプリケーション（券面入力補助AP）
	- 住基アプリケーション（住基AP）

高級なICカードってアプリが入るんです。電池とか入ってないのにどうなっているんだとかいろいろ気になります。その辺の仕組みはGoogleさんで検索するとたくさん出てきます。
本検証では`公的個人認証AP`にアクセスします。
公的個人認証APのデータにアクセスする場合、一部のデータはPINでロックを解除する必要があります。このPINがとっても重要です。

- PINは二つある
	- 署名用PIN（6～16桁の英数字）
	- 認証用PIN（4桁の数字）
- PINを何度か間違えるとロックがかかって使えなくなる
- **ロックを解除するには役所に行って申請書をかかないといけない**

**PINはマイナンバーカードを受け取るときに自分で決めているので普通は憶えていると思いますが、私のようによく憶えていないという人はちゃんとPINを確認しておきましょう。**

##２－３．公的個人認証APについて
JPKI-APともいいます。
APの下にファイル(FILE)があってその中にデータが格納されていたり、処理を行う関数が格納されているイメージです。
大きくは
- 利用者証明用電子証明書に関するFILE
- 署名用電子証明書に関するFILE
２つのグループに分かれています。⇒[参考:公的個人認証サービスによる電子証明書](http://www.soumu.go.jp/kojinbango_card/kojinninshou-01.html)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/252291/5fa281f9-8bc1-2152-e484-d52c2c045734.png)

|FILE|READ BINARY可能？|内容|説明|
|:-:|:-:|:---|:---|
|認証用証明書|〇|DER形式のバイナリデータ||
|認証用CA|〇|DER形式のバイナリデータ||
|認証用鍵|×|秘密鍵（Private Key）|アクセスにはPIN解除が必要。COMPUTE DIGITAL SIGNATUREコマンドを送って署名を作成することができます|
|認証用PIN|×|暗証番号（PIN）|PINは4桁の数字。VERIFYコマンドでロックを解除します。VERIFYを3回ミスるとアウト|
|署名用証明書|〇|DER形式のバイナリデータ|アクセスにはPIN解除が必要。|
|署名用CA|〇|DER形式のバイナリデータ||
|署名用鍵|×|秘密鍵（Private Key）|アクセスにはPIN解除が必要。COMPUTE DIGITAL SIGNATUREコマンドを送って署名を作成することができます|
|署名用PIN|×|暗証番号（PIN）|PINは6～16桁の英数字。VERIFYコマンドでロックを解除します。VERIFYを5回ミスるとアウト|

##２－４．APDUコマンドについて
カードの中にAPとかFILEがあって、READとかVERIFYとか言ってますが、どうやるんだという話です。
SCardTransmitの引数にバイナリ配列のコマンドを指定して、Responseを受けます。バイナリ配列のコマンドのことを`APDU`といいます。

`APDU`コマンドは色々種類があるんですが、ここで使うのは以下の4種類です。
- SELECT FILE ⇒　APとかFILEを選択する。CDコマンドみたいなものです。
- READ BINARY　⇒ データを読み出す。
- VERIFY　⇒　PINロックを解除する。
- COMPUTE DIGITAL SIGNATURE　⇒　電子署名を作成する。

APDUのResponseで`0x90、0x00`がGETできたら正常終了です。
本検証ではAPDUの詳細説明はしないで **おまじない** ということで話を進めます。

**APDUの詳細**
- [OpenSCでSuicaの利用履歴を読む方法と履歴データのフォーマット解析](https://qiita.com/gebo/items/cb2dd393170767852fb3)
- [WindowsでOpenSCを使ってMIFARE Standard(Classic)カードデータを読み出す方法](https://qiita.com/gebo/items/19f4fe7c24e12bb099eb)
- [EternalWindows-スマートカード](http://eternalwindows.jp/security/scard/scard07.html)


#おつかれさまでした

きりがいいので、今回はここまで。
⇒[#2](https://qiita.com/gebo/items/fa35c1f725f4c443f3f3)