以下の記事では、OpenSCというツールを使ってマイナンバーカードにアクセスしましたが、今回はOpenSCの内部で使われているAPDUプロトコルを使って電子署名をやってみたいと思います。
simple-minds-think-alike.moritamorie.com
まずは、ADPUプロトコルに関してまとめ、実際にAPDU命令をマイナンバーカードに送って結果をみていきたいと思います。
APDUプロトコルとは
APDU (Application Protocol Data Unit) プロトコルとは、接触型ICカードが準拠しているISO/IEC 7816の中で定められている通信規格で、この規格に準じてICカードとカードリーダー間の通信が行われることによって様々なICカードの間の相互互換性を維持できています。
APDUの構成・構成ユニット・パターン
構成
APDUは、以下の2つから構成されています。
構成ユニット
それぞれの構成ユニットは以下のようになっています。
Command APDU(C-APDU)
Response APDU(R-APDU)
パターン
C-APDUとR-APDU、それぞれの構成ユニットの組み合わせによって4パターンに分類されます。
使用するAPDUコマンド
本記事では以下3つのAPDUコマンドを使用します。
コマンド | CLS(命令クラス) | INS(命令コード) | 概要 | パターン |
---|---|---|---|---|
SELECT FILE | 00 | A4 | ファイルなどの論理チャネルを開く | パターン3 |
VERIFY | 00 | 20 | PINなどの確認 | パターン3 |
COMPUTE DIGITAL SIGNATURE | 80 | 2A | 電子署名の計算 | パターン4 |
COMPUTE DIGITAL SIGNATURE
のパラメータに関してはマイナンバーカード 独自の仕様のようです。
また、Response CommandのStatus Wordに関しては以下を参照しました。
APDUプロトコルで署名
前記事で使用した opensc-tool
というツールを使うとAPDUコマンドを送れるので今回も使います。
紹介する検証手順では opensc-tool
の実行を1回ずつ実行しているように記載していますが、実行すると途中でエラーが返ってきます。実際には以下のように &&
で繋げて実行しています。
$ opensc-tool -s 00:A4:04:0C:0A:D3:92:F0:00:26:01:00:00:00:01 && opensc-tool -s 00:A4:02:0C:02:00:1B && 〜〜〜
署名フロー
左側にフロー、右側にマイナンバーカードのデータ構造とした図を掲載しておきます。
①公的個人認証APをSELECT FILEする
- CLS(命令クラス): 00
- INS(命令コード): A4
- P1(引数1): 04
- P2(引数2): 0C
- Lc(データフィールド長): 0A (10進だと10。)
- Data: DF名 (D3 92 F0 00 26 01 00 00 00 01)
$ opensc-tool -s 00:A4:04:0C:0A:D3:92:F0:00:26:01:00:00:00:01 Using reader with a card: SCR3310 Smart Card Reader Sending: 00 A4 04 0C 0A D3 92 F0 00 26 01 00 00 00 01 Received (SW1=0x90, SW2=0x00)
②署名用PINをSELECT FILEする
- CLS(命令クラス): 00
- INS(命令コード): A4
- P1(引数1): 02
- P2(引数2): 0C
- Lc(データフィールド長): 02
- Data: ファイル識別子 (00 1B)
$ opensc-tool -s 00:A4:02:0C:02:00:1B Using reader with a card: SCR3310 Smart Card Reader Sending: 00 A4 02 0C 02 00 18 Received (SW1=0x90, SW2=0x00)
③署名用PINをVERIFYする
- CLS(命令クラス): 00
- INS(命令コード): 20
- P1(引数1): 00
- P2(引数2): 80
- Lc(データフィールド長): 05
- Data: パスワード(31 32 33 34 35)
- パスワードは12345を仮定しています。
- パスワードはアスキーコードで送ります。
$ opensc-tool -s 00:20:00:80:05:31:32:33:34:35 Sending: 00 A4 02 0C 02 00 0A Received (SW1=0x90, SW2=0x00)
④署名用秘密鍵をSELECT FILEする
- CLS(命令クラス): 00
- INS(命令コード): A4
- P1(引数1): 02
- P2(引数2): 0C
- Lc(データフィールド長): 02
- Data: ファイル識別子(00 1A)
$ opensc-tool -s 00:A4:02:0C:02:00:1A Received (SW1=0x90, SW2=0x00)
⑤電子署名する
まず、前記事で作成した署名対象のテキストデータファイルの中身を16進数で確認します。
$ xxd message.txt
00000000: 6865 6c6c 6f0a hello.
データは 6865 6c6c 6f0a
であることが分かりました。
この値をDataとして、COMPUTE DIGITAL SIGNATURE
を実行します。このコマンドによって署名用秘密鍵をマイナンバーカード の外に送らずに、署名を行うことができます。
- CLS(命令クラス): 80
- INS(命令コード): 2A
- P1(引数1): 00
- P2(引数2): 80
- Lc(データフィールド長): 06
- Data: 署名対象(68 65 6C 6C 6F 0A)
- Le(期待するレスポンスデータの長さ): 00
$ opensc-tool -s 80:2A:00:80:06:68:65:6C:6C:6F:0A:00 Received (SW1=0x90, SW2=0x00): 5C 9F CA FD 42 46 E3 A0 7B 34 19 B2 5F 5D 19 DB \...BF..{4.._].. BD F7 13 34 D0 1A 9D 96 29 15 02 4B 61 6A DA D4 ...4....)..Kaj.. CF 77 5C D0 A7 6D 80 F7 4E 8C FC BF A8 66 74 1F .w\..m..N....ft. 9A 2C ED 49 21 72 BD 74 86 16 73 D7 02 EC 4E C8 .,.I!r.t..s...N. E5 EB FE D1 EC 7D 76 18 4D D3 21 E6 2C 90 D2 70 .....}v.M.!.,..p 1F 2A 6B 79 DF 8E D3 0A 99 DB 46 61 7D 1C 3B AC .*ky......Fa}.;. C4 65 B2 BA 1B 76 CA FF 02 1A 7A D5 B1 47 30 4B .e...v....z..G0K 2B 20 0A 3C CE 06 9D D3 AB BD C4 89 A3 2F 7F 09 + .<........./.. 86 D9 C7 BE 8A 14 29 F7 6E A8 11 E9 1D 7D AA 01 ......).n....}.. E5 EE D7 F8 5A DC F8 61 ED ED 95 50 59 13 97 0C ....Z..a...PY... A6 71 22 F8 1E 3C 80 A2 A4 B0 BD 8A F3 F0 DF CF .q"..<.......... BB 65 A7 CD B9 84 2E 07 D8 6E 89 26 31 0C 46 91 .e.......n.&1.F. AD 1B 07 6A 1C 7F 2B 9B 42 CC AC CF F4 9A 86 23 ...j..+.B......# 9D 96 9D AE 87 D3 82 9A 7B CC C3 C5 91 4B A4 EF ........{....K.. 1A CA CC 14 BA 7B A7 CA B4 1E A7 EC 26 5B 49 0C .....{......&[I. EC 5F 85 92 7B 71 FE D0 6F 6A 40 75 D9 9E 9E 4D ._..{q..oj@u...M
署名付きデータ(5C〜4Dまで)を任意のバイナリエディタで保存し、text.sined
のように名前をつけて保存します。
署名検証してみる
前記事で作成した公開鍵(sign.pub)で検証すると同様に内容を確認できます。
$ openssl rsautl -verify -pubin -inkey sign.pub -in text.signed hello