スマホアプリにおける署名について

# Code Signing
iOS/Androidいずれの場合もアプリが改ざんされることを確認できる安全性を確保するために、ビルドしたアプリケーションに電子署名します。これがCode Signingとよばれます。
概念的には同じですが、ストアとの関係やツールの操作方法などがそれぞれ異なるため、混乱しそうです。
（これにビルドサイト（CircleCI/Bitrise等）を利用するとさらにサインするための情報を設定する必要があり、さらに複雑になります）

## 電子署名のざっくりした説明

### 電子署名する
電子署名は改ざんを防止や否認防止などで利用され、PKI（公開鍵インフラストラクチャ）の技術です。あるバイナリ（テキストデータもバイナリ化したうえで）を符号化した情報に対して秘密鍵で暗号化します。その値（A）と符号化、暗号化アルゴリズムを署名のメタデータとして含めます。

### 署名の検証
検証する場合は同様にバイナリを署名のメタデータである符号化アルゴリズムで符号化します。また含まれている暗号化された値（A）を公開鍵で複号化して一致しているかを確認します。
ここで元のバイナリが改ざんされると符号化された情報も変わるため一致しなくなり、改ざんされていることが検知されます。
公開鍵が改ざんされていると当然、この検証が無効になってしまうため、公開鍵が改ざんされていないかを確認します。そのため、公開鍵は証明書の形で受け渡され、その証明書は他の機関によって電子署名されているというチェーンによってその公開鍵の改ざんを検知します。
このあたりの保証・管理の仕方がPKIとして実現されています。

実際は、バイナリを分割してハッシュを取得したり、メタデータの格納方式などがAndroid、iOSで決まっています。

# 概要
上記のPKIの技術を使って、バイナリを保護することになりますが、Android／iOS共通して
* 証明書の取り扱い（証明書と紐付いた秘密鍵の取り扱い（鍵管理）
* アプリケーションID（バンドルID）
* 開発者
をどう結びつけるかという観点では同じものになります。

これらの取り扱いがそれぞれ違うことが難しさを呼んでるといえます。


# Android
## アプリへの署名の仕方
Android Studioのメニュー（Build>Generatote Signed Bundle or APK）から署名することができます。
この時にKey storeのパス（以下の鍵管理参照）、パスワード、鍵名称（エイリアス）、鍵パスワードが求められます。
この証明書の期限25年にしておくのが良いです（短くしたらGoogle Playでリリースできなかった）

### 鍵管理
AndroidのアプリでCode Signで必要な鍵を管理しているのは、JavaのKeystoreを利用しています。
但し、keytoolコマンドは利用せず、上記の通りAndroid Studioを使って利用することができます。

Keystoreは鍵管理ファイルとそのパスワード、各鍵の名称（鍵）とパスワードで構成されています。
この仕組からKeyStoreでは自己署名証明書と呼ばれる証明書にて管理されることになります。
IssuerとSubjectが同じ内容になり、iOSがAppleのCAによって署名された証明書を利用するのとは異なります。

### コマンドによる署名
Android Studioでも内部ではGradleを利用して署名しているので、CIなどのビルドプロセスで実行する場合はGradleでビルドをすることができます。以下にビルド方法を記載します。ソースコード（build.gradle)にパスワードを平文で記載するのはセキュリティ上、好ましくないのですが説明上、そうしていますので実際にはプロパティファイルに設定して、プロパティファイルを構成管理対象としないなどの工夫が必要となります。

```gradle:build.gradle
signingConfigs {
    release {
        keyAlias 鍵エイリアス
        keyPassword 鍵パスワード
        storeFile Key storeファイル名
        storePassword storeパスワード
    }
}

buildTypes {
    release {
        signingConfig signingConfigs.release
    }
}
```

### アプリケーションID
AndroidアプリのIDはAndroid Studioでプロジェクトを作るときに指定します。このIDは、appフォルダのbuild.gradleに設定されます。

```gradle:app/build.gradle
    defaultConfig {
        applicationId "xxx.xxx.xxx.xxx"

    }
```

このIDはGoogle Playで公開する際にURLの一部（play.google.com/store/apps/details?id=　このidの後ろにアプリIDをつける）となるため、重複しないようにJavaのパッケージと同様にドメインを逆に記載したものをもとに作成するのが良いと思います。

### Google Play 設定（開発者との紐付け）
リリースするにはGoogle Playにリリース登録する必要があります。
Google Play はGoogleの開発者登録をして、ログインできるようになるPlay Consoleからアプリを登録することができます。Consoleから作成した、アプリバンドルをアップロードしてリリース対象のファイルとします。（内部テストなどテストをへて、公開します）

また、Google PlayにはGoogle Play アプリ署名（アップロードする鍵と配布する鍵を変える）という機能があり、鍵管理の観点からはこちらを利用するのがいいと思います。

# iOS
iOSでもCode Signingが必要です。Google Playとは異なり、Apple Storeでは鍵を変えて署名してくれることはないので、ipaを作成するときに毎回署名します。

## 鍵管理
MacOSのアプリケーションであるKeyChainのアプリケーションにて、秘密鍵を管理します。正確に表現するとCSR（証明書要求）を作ったときに秘密鍵も作られることになります。
(AndroidではKey storeで管理しているのと同様です）

### 証明書の種類
署名で利用される秘密鍵に対応する署名書は二種類あります。

* Developer証明書（開発用）
* Distribution証明書(配布用）Adhoc配布とApple Store配布用です

### 証明書をCAにて署名する
オレオレ証明書ではなく、上記の証明書はそれぞれApple DeveloperサイトにてAppleの決まったCAによって電子署名して利用されます。（登録した証明書のみが利用できる）

そのため、上記で記載したCSRをもとにCAによって電子署名する方法で実現します。

#### Apple Developerサイトによる署名
PKIの一般用語では証明書をCAにて電子署名を依頼し、実施することでオレオレ証明書ではなく証明書チェーンに従う証明書にします。これをAppleのiOS開発においては「Certificates」にて登録、証明書を作成します。作成した証明書をダウンロードして、ダブルクリックすることでキーチェーンアプリにて秘密鍵と関連付けで保存されます。
この証明書はDER形式で保存されているので、openssslコマンドなどで中身を確認できます。

```bash
openssl x509 -inform der -in download.cer -text
```
などとすると中身がわかります。IssuerのOUは「Apple Worldwide Developer Relations」でした。
SubjectのCNが「Apple Distribution: XXX」になっていて、ここが配布用であることを表しています。

## アプリケーションID（Bundle ID)
Androidは内部の記載をもとにAPKファイルをアップロードする際に登録されていましたが、iOSの場合はApple Developerサイトで登録する必要があります。

Identifiersメニューから追加します。いろいろな種類がありますが、「App IDs」がスマホアプリのIDとなります。
Wildcard/ExplictのバンドルIDの種類を選んで設定します。

XCodeにここで登録したBundleIDとして設定をします。

## Provisioning File（開発者との紐付け）
AndroidはアップロードするAPKに含まれている署名が正になっており、PlayConsoleにログインしてアップロードすることでそのアップロード用の署名とユーザが紐付けられますが、iOSではアプリケーションID、証明書及び端末（Adhoc配布の場合など）をあわせてProfileを作成します。

### XCodeでの設定
このプロファイルを利用してアプリ署名を実施します。
コード署名を自動的にする設定をするとXCodeが自動的にプロファイルを作ってくれます。アプリケーションIDがなければ作成してくれます。証明書はAppleの署名が必要なので登録が必要ですが、アプリケーションID、プロファイルは作らなくて利用可能です。


# まとめ
PKIの知識をもっていれば、順をおって確認すればわかることですが、構成要素が多いのと使いやすくするためにツール化されているので少しわかり行くいと思いました。次は、iOSのコマンドでの手順を調べてCIできるサイトでの設定の理解（bitrise等）につなげたいと思います。