iOS アプリ開発に関連するトピックを提供しています。

Swift と CryptoTokenKit を使用して運転免許証のデータを取得する

日本の運転免許証は IC カードになっており、市販のカードリーダー等を使用することで IC チップに記録された各種情報を参照できます。macOS には標準で IC カードを読み込むためのフレームワークが用意されているので、カードリーダーさえ用意すればすぐに IC カードの情報を参照するアプリを作成することができます。

Python や Ruby などを使用して IC カードを参照するサンプルコードは多く見つかるのですが、Swift によるサンプルコードはほとんど見つかりません。そこで、macOS に標準で含まれている IC カード用のフレームワークである CryptoTokenKit を使用して、Swift で運転免許証のデータを取得するサンプルアプリケーションを作成しました。

github.com

環境構築

アプリを使用するためには、Mac に対応したカードリーダーが必要です。 今回は NTT コミュニケーションズ の ACR1251CL を使用しました。

NTTコミュニケーションズ ICカードリーダライタ ACR1251CL-NTTCom

NTTコミュニケーションズ ICカードリーダライタ ACR1251CL-NTTCom

ACR1251CL の接続端子は USB になります。 最近の Macbook Pro には USB-C 端子しかないため、以下の変換アダプターを中継して接続しています。

www.apple.com

アプリケーションの使用方法

github のレポジトリ からソースコードを取得したら、Xcode で開いてビルドします。あとは以下の手順でアプリケーションを操作してください。

  1. ICカードリーダーに運転免許証をセットします
  2. アプリを起動して運転免許証発行時に設定した PIN1、PIN2 を入力します
  3. 「データを取得」ボタンを押下すると、IC カードから記載事項を取得して画面に表示します

カードリーダーとの通信に成功すると以下の情報が表示されます。

  • 氏名
  • 生年月日
  • 免許証の交付年月日
  • 免許証の有効期限末日
  • 顔写真
  • 記載事項変更履歴

これらのデータは全て運転免許証の中に記録されており、ICチップと通信することで情報を取得しています。

なお、PIN1、PIN2 の入力に複数回失敗するとアクセスすることができなくなります。 その場合は運転免許センターまたは警察署での復旧手続きが必要となりますので、ご注意ください。

CryptoTokenKit

ここからは CryptoTokenKit フレームワークの使用方法について解説します。

フレームワークのインポート

CrypotTokenKit を使用するためには、アプリケーションの entitlements ファイルに以下の文字列を追加します。

com.apple.security.smartcard

f:id:watanabetoshinori:20190525161853p:plain

その後、任意のソースコードでフレームワークをインポートします。

import CryptoTokenKit

IC カードの取得

カードリーダーのスロットにアクセスして、IC カードを取得します。 IC カードは TKSmartCard クラスのインスタンスとして取得されます。

let manager = TKSmartCardSlotManager.default!

let slotName = manager.slotNames.first!

manager.getSlot(withName: slotName) { (slot) in
    let smartCard = slot.makeSmartCard()
}

コマンドの送信

取得したスマートカードに対してコマンドを送信します。 コマンドは APDU (Application Protocol Data Unit) と呼ばれるデータ形式で送受信します。

Swift のコード上では以下のような UInt8 形式の配列を送信します。

// セッション開始
smartCard.beginSession { (success, error) in

    // コマンド を送信
    let apdu: [UInt8] = [0x00, 0xA4, 0x02, 0x0C, 0x00, 0x01, 0x02]
    let apduData = Data(bytes: apdu, count: apdu.count)

    smartCard.transmit(apduData) { (data, error) in
        // 結果を処理

        // セッションを切断
        smartCard.endSession()
    }

}

処理結果は Data または Error として返されます。 この例では1つのコマンドを送信してセッションを終了していますが、実際に IC カードの情報を参照する際には複数のコマンドを順番に送信する必要があります。

送信するコマンドや返されるデータは IC カードごとに異なるため、各カードの仕様に従い処理を実装する必要があります。 運転免許証の場合は インターネット上で公開されている仕様書 が見つかりますので、そちらを参考に実装を行いました。

サンプルアプリケーション

今回の サンプルアプリケーション には以下のコードも含まれています。詳しくはレポジトリの各コードを参照してください。

  • CryptoTokenKit の非同期処理 (beginSession / transmit)を同期処理にした拡張クラス
  • 運転免許証が返すデータ (TLV) をパースするクラス
  • 運転免許証が返すデータを文字列に変換するクラス(JISX0201 / JISX0208 / 日付に対応)

For iOS ?

iOS にも CryptoTokenKit は含まれていますが、iOS 12 時点ではプライベートフレームワークになっているため一般のアプリから利用することはできません。