業務でAndroid開発をしていて、都合上、後から鍵ペアを人に渡さなければいけない場合があります。
新しいapkのたびにキーストアファイルを作っているのなら、別にそれごと渡してしまえばいいのですが、自分用のキーストアに作ってしまった場合、キーストアごと渡すわけにはいきません。
そこでキーストアファイルから証明書をエクスポートして相手に渡すことを考えますが、apkに署名するには、証明書の他に秘密鍵が必要です。
先に結論だけ書いておきます。keytoolコマンドのimportkeystoreを使います。
> keytool -importkeystore -srckeystore .\mykeystore.jks -srcstorepass <<自分のキーストアのパスワード>> -destkeystore app1.jks -deststorepass <<新規作成するキーストアのパスワード>> -deststoretype jks -srcalias app1 <app1> の鍵パスワードを入力してください。
これでapp1.jksというキーストアファイルが新規作成され、自分のキーストアの中から特定のエイリアスの鍵ペアだけをコピーできます。
以下は説明です。
例えば自分用のキーストアの中身がこうなっていたとします。
> keytool -list -v -keystore .\mykeystore.jks -storepass <<キーストアのパスワード>> キーストアのタイプ: JKS キーストアのプロバイダ: SUN キーストアには 2 エントリが含まれます。 別名: app1 作成日: 2012/03/08 エントリタイプ: PrivateKeyEntry 証明連鎖の長さ: 1 証明書[1]: 所有者: C=JP 発行者: C=JP シリアル番号: 4f582f00 有効期間の開始日: Thu Mar 08 00:00:00 JST 2012 終了日: Wed Jul 10 00:00:00 JST 3011 証明書のフィンガープリント: MD5: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 SHA1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 署名アルゴリズム名: SHA1withRSA バージョン: 3 ******************************************* ******************************************* 別名: app2 作成日: 2012/03/08 エントリタイプ: PrivateKeyEntry 証明連鎖の長さ: 1 証明書[1]: 所有者: C=JP 発行者: C=JP シリアル番号: 4f57f300 有効期間の開始日: Thu Mar 08 00:00:00 JST 2012 終了日: Wed Jul 10 00:00:00 JST 3011 証明書のフィンガープリント: MD5: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 SHA1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 署名アルゴリズム名: SHA1withRSA バージョン: 3
証明書のエクスポートとインポートは以下のコマンドでできますが、秘密鍵がエクスポートできません。
> keytool -exportcert -keystore .\mykeystore.jks -storepass <<キーストアのパスワード>> -alias app1 -file .\app1.cer 証明書がファイル <.\app1.cer> に保存されました。 > keytool -import -keystore app1.jks -storepass <<新規作成するキーストアのパスワード>> -file .\app1.cer 所有者: C=JP 発行者: C=JP シリアル番号: 4f582f00 有効期間の開始日: Thu Mar 08 00:00:00 JST 2012 終了日: Wed Jul 10 00:00:00 JST 3011 証明書のフィンガープリント: MD5: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 SHA1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 署名アルゴリズム名: SHA1withRSA バージョン: 3 この証明書を信頼しますか? [no]: yes 証明書がキーストアに追加されました。
この状態のキーストアはこうなっています。
> keytool -v -list -keystore .\app1.jks -storepass <<キーストアのパスワード>> キーストアのタイプ: JKS キーストアのプロバイダ: SUN キーストアには 1 エントリが含まれます。 別名: app1 作成日: 2012/03/31 エントリのタイプ: trustedCertEntry 所有者: C=JP 発行者: C=JP シリアル番号: 4f582f00 有効期間の開始日: Thu Mar 08 00:00:00 JST 2012 終了日: Wed Jul 10 00:00:00 JST 3011 証明書のフィンガープリント: MD5: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 SHA1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 署名アルゴリズム名: SHA1withRSA バージョン: 3 ******************************************* *******************************************
エントリのタイプがtrustedCertEntryになっています。このエントリでapkを署名しようとするとjarsignerがエラーを出します。
jarsigner: 次の証明連鎖が見つかりません: app1。 app1 は、非公開鍵および対応する公開鍵証明連鎖を含む有効な KeyStore 鍵エントリを参照する必要があります。 (英語の場合) jarsigner: Certificate chain not found for: app1. app1 must reference a valid KeyStore key entry containing a private key and corresponding public key certificate chain.
Eclipseの場合は、何も言われず、Finishボタンが押せません。
ここで最初の結論のところで書いたimportkeystoreを使って、キーストアからキーストアへのインポートをすることで、秘密鍵を持ったまま新しいキーストアに証明書をコピーできます。コピー後のキーストアファイルはこうなります。
> keytool -list -v -keystore .\app1.jks -storepass <<キーストアのパスワード>> キーストアのタイプ: JKS キーストアのプロバイダ: SUN キーストアには 1 エントリが含まれます。 別名: app1 作成日: 2012/04/01 エントリタイプ: PrivateKeyEntry 証明連鎖の長さ: 1 証明書[1]: 所有者: C=JP 発行者: C=JP シリアル番号: 4f582f00 有効期間の開始日: Thu Mar 08 00:00:00 JST 2012 終了日: Wed Jul 10 00:00:00 JST 3011 証明書のフィンガープリント: MD5: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 SHA1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 署名アルゴリズム名: SHA1withRSA バージョン: 3
エントリタイプがPrivateKeyEntryになっていれば、通常通りapkの署名に使えます。
あと、importkeystoreが使えるのはJDK6以降のようなので、バージョンは確認してください。
[…] アプリを複数のメンバで開発していて、開発者ごとに別々のキーストアを使用していると、証明書が異なるAPKファイルは上書きインストールできないので、一旦削除してからインストールすることになります。また、Googleマップを使用する場合のAPIキーの取得に証明書が必要で、結果APIキーも開発者ごとに異なってしまいます。これでは手間がかかるので、複数のメンバで開発する場合はキーストアを共用するのがいいでしょう。Eclipseメニューの「ウィンドウ」→「設定」→左ペイン「Android」→「ビルド」とした右ペインの「カスタム・デバッグ・キーストア」欄に共通のキーストアを指定します。(参考サイト:開発用署名 debug.keystore、Androidにおけるセキュリティ設計と動作(前編)、Androidのキーストアから証明書をエクスポートする) […]