鍵を生成してAPKファイルに署名をする

# apkファイルに署名するまでの流れ
apkファイルに署名するまでの流れをざっくり書きます。
1. 非公開鍵を格納するキーストアファイルと、そこに格納する非公開鍵（キー）を生成する。
2. 生成したキーストアファイルと、非公開鍵（キー）を使い、apkファイルに署名をする。

#1. 非公開鍵を格納するキーストアファイルと、そこに格納する非公開鍵（キー）を生成する。
## キーストアと、キーを生成する
下記のコマンドでキーストアと、キーを生成します。

```
rintaro$ keytool -genkey -v \
> -keystore hoge.keystore \
> -storepass pass_keystore \
> -alias alias_key1 \
> -keypass pass_key1 \
> -keyalg RSA \
> -validity 10
```
＊Windowsの方は、`^`で改行できるかと。

**keytool のオプション説明**
[JAVA Documentation | keytool - 鍵と証明書の管理ツール](https://docs.oracle.com/javase/jp/6/technotes/tools/solaris/keytool.html)を参考にしました。

- v
    - 「冗長」モードで実行され、詳細な証明書情報が出力される。
- genkeypair(旧名 genkey)
    - 鍵のペア (公開鍵および関連する非公開鍵) を生成する。
- keystore
    - キーストアの場所を指定する。指定しなければ.keystoreという名前のデフォルトキーストアファイルが、ユーザのホームディレクトリに作成される。（.keystoreがすでにある場合は、それを使う）
- storepass
    - キーストアのパスワードを指定する。
- alias
    - キーストアに保存するキーの名前（エイリアス）を指定する。
- keypass
    - キーのパスワードを指定する。
- keyalg
    - 鍵のペアを生成するのに使うアルゴリズムを指定する。
        - [RSA暗号の仕組み](https://qiita.com/jabba/items/e5d6f826d9a8f2cefd60)
- validity
    - 証明書の有効日数を指定する。

コマンドを実行すると、下記のようにいくつか聞かれたのですが、全て空白のままenterして、最後だけ`y`を入力しました。

```
姓名は何ですか。
  [Unknown]:

組織単位名は何ですか。
  [Unknown]:

組織名は何ですか。
  [Unknown]:

都市名または地域名は何ですか。
  [Unknown]:

都道府県名または州名は何ですか。
  [Unknown]:

この単位に該当する2文字の国コードは何ですか。
  [Unknown]:

CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknownでよろしいですか。
  [いいえ]:  y

10日間有効な2,048ビットのRSAの鍵ペアと自己署名型証明書(SHA256withRSA)を生成しています
        ディレクトリ名: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
[hoge.keystoreを格納中]
```

### 生成したキーストアの内容を確認する
```
rintaro$ keytool -list -v \
> -keystore hoge.keystore \
> -storepass pass_keystore
```
コマンドを実行すると、キーストアの情報と、そこに格納されているキーの情報が表示されるかと思います。

ここまでが、冒頭で書いた「1.非公開鍵を格納するキーストアファイルと、そこに格納する非公開鍵（キー）を生成する。」になります。

# 2.生成したキーストアファイルと、非公開鍵（キー）を使い、apkファイルに署名をする。
## apkファイルに署名する
下記のコマンドで、apkファイルに署名をします。

```
rintaro$ jarsigner -verbose \
> -keystore hoge.keystore \
> -storepass pass_keystore \
> -keypass pass_key1 \
> android-release-unsigned.apk \
> alias_key1
```

**jarsignerオプションの説明**
[JAVA Documentation | jarsigner](https://docs.oracle.com/javase/jp/8/docs/technotes/tools/unix/jarsigner.html)を参考にしました。

- verbose
    - 冗長モードで動作し、JARの署名または検証の進行状況に関する追加情報を出力する。
- keystore
    - キーストアの場所を示すURLを指定する。検証の際は必要ない。
- storepass
    - キーストアのパスワードを指定する。
- keypass
    - キーのパスワードを指定する。

コマンドを実行すると、下記が表示されました。

```
 更新中: META-INF/MANIFEST.MF
   追加中: META-INF/ALIAS_KE.SF
   追加中: META-INF/ALIAS_KE.RSA
  署名中: AndroidManifest.xml
  署名中: assets/www/cordova-js-src/android/nativeapiprovider.js
  署名中: assets/www/cordova-js-src/android/promptbasednativeapi.js
  署名中: assets/www/cordova-js-src/exec.js
  署名中: assets/www/cordova-js-src/platform.js
  署名中: assets/www/cordova-js-src/plugin/android/app.js
  署名中: assets/www/cordova.js
  署名中: assets/www/cordova_plugins.js
  署名中: assets/www/css/index.css
  署名中: assets/www/img/logo.png
  署名中: assets/www/index.html
  署名中: assets/www/js/index.js
  署名中: classes.dex
  署名中: res/drawable-land-hdpi-v4/screen.png
  署名中: res/drawable-land-ldpi-v4/screen.png
  署名中: res/drawable-land-mdpi-v4/screen.png
  署名中: res/drawable-land-xhdpi-v4/screen.png
  署名中: res/drawable-land-xxhdpi-v4/screen.png
  署名中: res/drawable-land-xxxhdpi-v4/screen.png
  署名中: res/drawable-port-hdpi-v4/screen.png
  署名中: res/drawable-port-ldpi-v4/screen.png
  署名中: res/drawable-port-mdpi-v4/screen.png
  署名中: res/drawable-port-xhdpi-v4/screen.png
  署名中: res/drawable-port-xxhdpi-v4/screen.png
  署名中: res/drawable-port-xxxhdpi-v4/screen.png
  署名中: res/mipmap-hdpi-v4/icon.png
  署名中: res/mipmap-ldpi-v4/icon.png
  署名中: res/mipmap-mdpi-v4/icon.png
  署名中: res/mipmap-xhdpi-v4/icon.png
  署名中: res/mipmap-xxhdpi-v4/icon.png
  署名中: res/mipmap-xxxhdpi-v4/icon.png
  署名中: res/xml/config.xml
  署名中: resources.arsc
jarは署名されました。

警告:
署名者の証明書は6か月以内に期限切れになります。
-tsaまたは-tsacertが指定されていないため、このjarにはタイムスタンプが付加されていません。タイムスタンプがないと、署名者証明書の有効期限(2018-02-25)後または将来の失効日後に、ユーザーはこのjarを検証できない可能性があります。
```
署名はできているっぽいのですが、警告が気になるので調べたところ、[こちらのサイト](http://blog.ysakaguchi.net/2014/10/apk-tsa-tsacertjar.html)を発見。
書いてある通り`-tsa http://timestamp.digicert.com`オプションを追加して実行してみたところ、うまく行きました。

実行と、その結果は下記になります。

```
rintaro$ jarsigner -verbose \
> -tsa http://timestamp.digicert.com \
> -keystore hoge.keystore \
> -storepass pass_keystore \
> -keypass pass_key1 \
> android-release-unsigned.apk \
> alias_key1


 更新中: META-INF/ALIAS_KE.SF
シグネチャ・タイムスタンプのリクエスト
TSAの場所: http://timestamp.digicert.com
 更新中: META-INF/ALIAS_KE.RSA
  署名中: AndroidManifest.xml
  署名中: assets/www/cordova-js-src/android/nativeapiprovider.js
  署名中: assets/www/cordova-js-src/android/promptbasednativeapi.js
  署名中: assets/www/cordova-js-src/exec.js
  署名中: assets/www/cordova-js-src/platform.js
  署名中: assets/www/cordova-js-src/plugin/android/app.js
  署名中: assets/www/cordova.js
  署名中: assets/www/cordova_plugins.js
  署名中: assets/www/css/index.css
  署名中: assets/www/img/logo.png
  署名中: assets/www/index.html
  署名中: assets/www/js/index.js
  署名中: classes.dex
  署名中: res/drawable-land-hdpi-v4/screen.png
  署名中: res/drawable-land-ldpi-v4/screen.png
  署名中: res/drawable-land-mdpi-v4/screen.png
  署名中: res/drawable-land-xhdpi-v4/screen.png
  署名中: res/drawable-land-xxhdpi-v4/screen.png
  署名中: res/drawable-land-xxxhdpi-v4/screen.png
  署名中: res/drawable-port-hdpi-v4/screen.png
  署名中: res/drawable-port-ldpi-v4/screen.png
  署名中: res/drawable-port-mdpi-v4/screen.png
  署名中: res/drawable-port-xhdpi-v4/screen.png
  署名中: res/drawable-port-xxhdpi-v4/screen.png
  署名中: res/drawable-port-xxxhdpi-v4/screen.png
  署名中: res/mipmap-hdpi-v4/icon.png
  署名中: res/mipmap-ldpi-v4/icon.png
  署名中: res/mipmap-mdpi-v4/icon.png
  署名中: res/mipmap-xhdpi-v4/icon.png
  署名中: res/mipmap-xxhdpi-v4/icon.png  署名中: res/mipmap-xxxhdpi-v4/icon.png
  署名中: res/xml/config.xml
  署名中: resources.arsc
jarは署名されました。

警告:
署名者の証明書は6か月以内に期限切れになります。
```
## 署名できているか確認する
次のコマンドで、署名ができているかを確認できます。

```
jarsigner -verify -verbose -keystore <署名に使用したkeystoreのパス> -certs <apkファイル名>
```

<font color="Red">
**注意**
keystoreオプションを省略すると、`~/keystore`をデフォルトでみに行きます。今回の場合は`hoge.keystore`を指定しています。
</font>

```
jarsigner -verify -verbose -keystore ./hoge.keystore -certs ./hoge.apk
```

実行すると、次のようなログが出力され、署名できていることを確認できました。

```
s k     3505 Fri Feb 16 13:45:18 JST 2018 META-INF/MANIFEST.MF

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

        3649 Fri Feb 16 13:45:18 JST 2018 META-INF/ALIAS_KE.SF
        1370 Fri Feb 16 13:45:18 JST 2018 META-INF/ALIAS_KE.RSA
smk     2708 Fri Nov 30 00:00:00 JST 1979 AndroidManifest.xml

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     1322 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova-js-src/android/nativeapiprovider.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     1441 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova-js-src/android/promptbasednativeapi.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    11143 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova-js-src/exec.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     4924 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova-js-src/platform.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     4005 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova-js-src/plugin/android/app.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    72748 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk      210 Fri Nov 30 00:00:00 JST 1979 assets/www/cordova_plugins.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     3719 Fri Nov 30 00:00:00 JST 1979 assets/www/css/index.css

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    21814 Fri Nov 30 00:00:00 JST 1979 assets/www/img/logo.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     2513 Fri Nov 30 00:00:00 JST 1979 assets/www/index.html

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     1664 Fri Nov 30 00:00:00 JST 1979 assets/www/js/index.js

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   143720 Fri Nov 30 00:00:00 JST 1979 classes.dex

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   216014 Fri Nov 30 00:00:00 JST 1979 res/drawable-land-hdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    41538 Fri Nov 30 00:00:00 JST 1979 res/drawable-land-ldpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    90490 Fri Nov 30 00:00:00 JST 1979 res/drawable-land-mdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   488469 Fri Nov 30 00:00:00 JST 1979 res/drawable-land-xhdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   674457 Fri Nov 30 00:00:00 JST 1979 res/drawable-land-xxhdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   832779 Fri Nov 30 00:00:00 JST 1979 res/drawable-land-xxxhdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   220338 Fri Nov 30 00:00:00 JST 1979 res/drawable-port-hdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    41064 Fri Nov 30 00:00:00 JST 1979 res/drawable-port-ldpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    90555 Fri Nov 30 00:00:00 JST 1979 res/drawable-port-mdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   501006 Fri Nov 30 00:00:00 JST 1979 res/drawable-port-xhdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   692467 Fri Nov 30 00:00:00 JST 1979 res/drawable-port-xxhdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk   919644 Fri Nov 30 00:00:00 JST 1979 res/drawable-port-xxxhdpi-v4/screen.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     5217 Fri Nov 30 00:00:00 JST 1979 res/mipmap-hdpi-v4/icon.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     2230 Fri Nov 30 00:00:00 JST 1979 res/mipmap-ldpi-v4/icon.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     3202 Fri Nov 30 00:00:00 JST 1979 res/mipmap-mdpi-v4/icon.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     6794 Fri Nov 30 00:00:00 JST 1979 res/mipmap-xhdpi-v4/icon.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     8901 Fri Nov 30 00:00:00 JST 1979 res/mipmap-xxhdpi-v4/icon.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk    10963 Fri Nov 30 00:00:00 JST 1979 res/mipmap-xxxhdpi-v4/icon.png

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     2436 Fri Nov 30 00:00:00 JST 1979 res/xml/config.xml

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]

smk     3384 Fri Nov 30 00:00:00 JST 1979 resources.arsc

      X.509, CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown (alias_key1)
      [証明書は18/02/25 17:12に失効します]


  s=シグネチャが検証されました
  m=エントリがマニフェスト内にリストされます
  k=1つ以上の証明書がキーストアで検出されました
  i=1つ以上の証明書がアイデンティティ・スコープで検出されました

- 署名者: "CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown"
    ダイジェスト・アルゴリズム: SHA-256
    署名アルゴリズム: SHA256withRSA、2048ビット鍵

jarが検証されました。

警告:
このjarには、署名者の証明書が6か月以内に期限切れとなるエントリが含まれています。
```
これで、署名付きのAPKファイルの作成が完了しました！

# 参考サイト
- [Android 作成したアプリに署名を行う](http://blue-red.ddo.jp/~ao/wiki/wiki.cgi?page=Android+%BA%EE%C0%AE%A4%B7%A4%BF%A5%A2%A5%D7%A5%EA%A4%CB%BD%F0%CC%BE%A4%F2%B9%D4%A4%A6)
- [Cordova で Android リリースビルドして Google Play リリース用 apk を作る方法](http://phiary.me/cordova-android-release-build-apk-for-google-play/)