2011年08月31日

Android 上のアプリから SSL クライアント認証の必要なサーバへアクセスする方法

はてなブックマークに登録

Android の Web ブラウザが SSL クライアント認証に対応していないのは不便だという話を以前このブログに書きました。記事では、Android 上の stone に SSL まわりの処理を代行させる方法について触れました。
Android 上のブラウザから SSL クライアント認証の必要なサーバへアクセスする方法


それから半年、本家の Android 標準ブラウザは現在も未対応のままですが、「SandroB」のようにクライアント認証に独自対応したブラウザも登場し始めています。こうした動きは Android ユーザとしてとても喜ばしいことで、対応環境の拡大や機能面の向上など今後の進化が大いに期待されます。

一方で、たとえば KLab の「VPN-Warp」のような SSL-VPN システム経由での利用が想定されるアプリケーションは Web ブラウザばかりではありません。私の場合、出先から自宅 PC へのアクセスには VNC を VPN-Warp+stone 経由で使っています。VNC ビューワそのものは SSL に対応していませんが、通信に stone を介在させることで所定のアプリ本体が SSL まわりの実装を持っていなくてもそういう使い方が可能となるわけですね。もちろん、人によってはここで言う「所定のアプリ」に、「普段使い慣れているブラウザ」が該当する場合もあるでしょう。

冒頭の記事を書いた時点では Android 用 stone は何かと面倒な CUI ベースでしたが、現在は通常の Android アプリとしてマーケットで公開しています。社内からの声もあり、今回はこのアプリ版に固有の Android キーストアへ証明書をインストールする機能に関する話題に触れながら、stone for Android でクライアント証明書を利用する手順等を紹介します。


■ Android キーストアと Android アプリの間の微妙な関係

Andorid 2.x 以上では [設定]−[現在地情報とセキュリティ]−[SDカードから (または「ストレージからの」) インストール] より、所定の証明書をシステムのキーストアである認証情報ストレージ (Credential Storage) へインストールすることができます。
この操作での一連の流れは Windows 環境上でキーストアへ証明書をインポートする際のそれと似ているため Windows でその手順を経験したことのある人にはこれといって違和感のあるものではないでしょう。しかし、内部的にはとても大きな違いがあります。Android では、上記の手順でキーストアへインストールした証明書を自作のアプリケーションから参照することができないのです。これは以下の理由によるものです。

  • Android の [設定] (パッケージ名:com.android.settings) は、uid=system (1000) で実行されるシステムアプリである
  • 一般の Android アプリには端末へのインストール時にシステムにより固有の uid が割り当てられ常にその uid で実行される
  • 「証明書のインストールを行ったプロセスの uid の情報」は、「キーストアに配置された証明書データのファイル名」に反映される (※1)
  • 特権 uid 以外で実行中のプロセスがキーストア内の証明書を参照するには、そのプロセスの uid と、対象とする証明書のインストールを実施したプロセスの uid が一致していなければならない (この処理の記述された Android ソース→keystore.c
(※1) たとえば、「mycert.p12」 という 一件のクライアント証明書・秘密鍵のペアと 一件の CA 証明書を含む pkcs12 形式の証明書ファイルを上記の要領で [設定] からインストールすると、キーストアの実体である /data/misc/keystore/ 下には以下のネーミングでファイルが配置される。"1000_" の部分が uid。

  • 1000_USRCERT_mycert
  • 1000_USRPKEY_mycert
  • 1000_CACERT_mycert

また、次の点にも注意が必要です。

  • あるアプリの uid は、そのアプリが別のプロセスからのインテント発行をトリガーに起動した場合においてもインテント発行元のプロセスの uid の影響を受けない
    (親子プロセスの関係にはならない)


■ stone for Android での証明書インストール対応方法

システムがキーストアを持っているにもかかわらず自作のアプリからそれを利用できないというのはどうにも残念です。stone は証明書をファイルベースで参照することができるためキーストアへの証明書インストールが実用上必須というわけではありませんが、証明書のパスワードをファイルとして端末に配置することのリスクや、証明書パスワードを記憶し管理し続けることのコストを考えればやはりキーストアを利用したいところです。
もちろん、別の対処方法としてアプリ独自のキーストア機構を用意し証明書データの暗号化と復号を自前で処理するといったことも考えられますが、オープンソースの Android ですから、こうした場合、どのように対応すれば実現したい処理をシステム側の事情にうまく馴染ませることができるかを調べてみる価値は大いにありそうです。

大枠で次のように考えました。
「システムアプリのプロセスから証明書インストール処理が呼び出されると具合が悪いのなら、そこで使用されているインストール処理用の最小限のコードを自分のアプリに組み込んでしまえばよいのではないか?」
もっとスマートな方法もあるかもしれませんが、つまりは自作アプリにキーストアへの証明書インストール機能を実装しちゃえということですね。インテント経由で Android システムの証明書インストール機能を呼び出すのではなく 自分の処理の一部として証明書のインストールをハンドリングすれば、そこに反映される uid は確実に自作アプリ自身のプロセスのものとなるはずです。

ソースを調べてみると [設定] からの証明書インストール処理は「CertInstaller」というシリーズのコードに記述されていることがわかりました。 それから最終的に以下の 3 つのディレクトリから 10 本のソースコードをピックアップし、ライセンス規約に準じた形でアプリへの組み込みを行いました。

stone for Android の証明書インストール機能はこのようにして実装しています。 当初の期待通り、組み込んだ「証明書のインストール」機能を使ってインストールした証明書は同アプリの uid 識別とともにキーストアへ配置され stone 実行時に正しく参照することができています。持ち込んだソースの中には削ることの可能なコードもまだ残っていますが、そこにはいずれゆっくり手をつけることにしましょう :-)


■ クライアント証明書をインストールしてみる

上述の通り stone for Android は Android 2.x 以上の環境において Android キーストアへの証明書のインストールと参照に対応しています。ここでは証明書をインストールする手順をざっくりまとめてみます。
アプリケーションメニューの「証明書のインストール」をタップして下さい。



ここで上図 A) のメッセージが表示された場合は下記リンクの図を参考にキーストアにパスワードを設定した上で再度上記の操作を行って下さい。
Android キーストアへのパスワード設定手順

上図 B) のメッセージはキーストアのパスワード保護が解除されていない場合に表示されます。端末の電源を投入した時点ではキーストアはロックされた状態です。設定ずみのパスワードを投入し「OK」を押下するとロックが解除されます。

キーストアへアクセス可能な状態であれば stone for Android は次のいずれかのディレクトリ下に存在する *.p12, *.pfx 等の証明書ファイルを一覧表示します。
  • [外部ストレージディレクトリ]/   (※2)
  • [外部ストレージディレクトリ]/download/
(※2) 外部ストレージディレクトリとは 当該環境において android.os.Environment の getExternalStorageDirectory() が指し示すディレクトリであり、伝統的には 「/mnt/sdcard」 や 「/sdcard」 がこれに該当する
インストール対象とする証明書ファイル名をタップし、図の手順でキーストアへのインストールを行います。
インストールが完了すると、その証明書を参照する stone パラメータ記述例が GUI のパラメータフィールドに提示されます。リモートホスト名の指定箇所は「SERVERNAME」とダミー表記されており、その他の指定を含めこのサンプルを編集すれば効率がよいでしょう。
なお、サンプルパラメータで上書きされる前の stone パラメータは履歴として保存されており履歴一覧から簡単に呼び戻せます。


■ インストールずみのクライアント証明書を使ってみる

インストールしたクライアント証明書を参照する stone プロセスに SSL 処理一式をまかせ、所定のアプリからリモートサーバへアクセスした例を図に示します。

stone パラメータの文法解説はアプリケーションメニューの [ヘルプ] から参照できます。応用の際などに利用して下さい。


(tanabe)
klab_gijutsu2 at 10:06│Comments(0)TrackBack(0)Android | win

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント