shoota works

Java(Android)でHTTPSクライアント認証

Java(Android)でHTTPSクライアント認証
Photo by

日本語で簡潔に説明されているものを探せず苦労したので雑にメモ。検索するとサーバ証明書関連が多くて、Android アプリをクライアント認証させるのはあまり多い事例じゃないっぽい。

そもそも HTTPS 認証ってなにかを雑に

証明書によって認証する。認証はドメイン(common name)単位で署名される。
サブドメインはワイルドカード指定可能(google の場合だと*.google.comになってる)。
Android に関する証明書形式の対応はnexus のヘルプページが参考になる。

HTTPS サーバ認証の雑な説明

  • https 通信の信頼性を検証し、クライアントがサーバを信頼するために使用する。
  • クライアントは他者(認証局:CA)の署名を信頼し、その署名をもつサーバを信頼する。
  • 不特定多数のユーザに公開されているサービスで使用する。
  • 形式はX.509、拡張子は.crt一般的と思われる。
  • CA の署名(とその証明書)がサーバ証明書を証明する。
  • すなわち CA 証明書はサーバ証明書の証明書
  • CA の証明書は自己証明書。
  • Android にはグローバルな CA 証明書が最初から組込まれている。
  • Android に後入れした CA 証明書は Chrome で使用できる。

HTTPS クライアント認証の雑な説明

  • https で認証されたサーバが、特定のクライアントのみを受け付けるために行う認証。
  • 認証局が署名した証明書で署名される。通常、クライアント証明書には署名した CA 証明書が含まれる。
  • インターネット上の特定多数(特定多数がイントラネットでしばれない)ユーザにのみサービスを公開する場合のプロトコルレベルでの認証。
  • 形式はPKCS#12、拡張子は.p12

HTTPS クライアント認証:サーバサイド(Apache2.2 以上)

crt 作成と認証局署名を行い、証明書をサーバに配置して通常の https 設定の上、クライアント認証設定を追加する。
方法はmod_ssl のドキュメントの通り、SSLVerifyClient requireを特定ドメインに設定する。

クライアント認証の対象を path で絞りたい場合は<Directory><Location>を使う。さらに ajp でリバースプロキシしている場合は以下のように行う。

# default is none.
SSLVerifyClient none
## ajp reverse proxy setting
ProxyPass / ajp://localhost/
 
# client certification for specific path
<IfModule mod_proxy_ajp.c>
  <Location /secret/>
  SSLVerifyClient require
 </Location>
</IfModule>

HTTPS クライアント認証:Android app(API レベル 8,21 で確認)

org.apache.http.impl.client.DefaultHttpClientで GET/POST をするときに以下のメソッドで Https スキーマを登録しておく。
クライアント証明書は/assetに入れておく前提。

ついでに

通常の HTTPS サーバ認証については、JSSEC のサンプルが参考になる