先週、私はチームに「学習報告」を行いました。実際には、チームで毎週行われる技術共有で、誰もが機会を持つのですが、今回は私の番でした。では、チームの新人として、何を話すべきでしょうか?
考えを巡らせていると、以前からよく直面していた厄介な問題を思い出しました:実機で iOS プロジェクトを実行する際、プロジェクトがまだ起動していないのに、プロジェクト設定の署名(Targets > Signing & Capabilities)でエラーが出ることがある。自分のプロジェクトでも、サードパーティのオープンソースライブラリでも、会社のプロジェクトでも同様です。
毎回 Google や同僚に尋ねれば答えを見つけることができるものの、なぜそれが解決できるのか、またなぜ実機で iOS プロジェクトを実行するのに署名が必要なのか、私はそれらについて半分理解しているだけで、混乱していました。
しかし、今ではその背後にある秘密をついに理解しました!もしあなたも同じような疑問を抱えているなら、以下を読み進めてください。きっと完全に理解できるようになります ——iOS 署名の背後にある原理!
本文の目的#
この記事を読み終えると、以下の問題を簡単に解決できる能力を持つことができます:
- 実機で自分の iOS プロジェクトや iOS オープンソースライブラリを実行するにはどうすればよいか?
- 実機で会社の iOS プロジェクトを実行するにはどうすればよいか?
さらに、この記事の最終目標は、iOS 署名に関連する問題に直面したときに、迅速に解決できるようになることです。
予備知識:デジタル署名 & デジタル証明書#
iOS 署名について話す前に、インターネットの世界における署名✒️と証明書📄の 2 つの予備知識を理解する必要があります。
参考:デジタル署名とデジタル証明書とは?—— 阮一峰
デジタル署名#
デジタル署名は、送信されるデータに添付され、データの改ざんを防ぐために使用されます。
その基盤となるコアはハッシュ混乱アルゴリズムと非対称暗号技術(公開鍵 / 秘密鍵)です。
生成#
署名 Signature の生成は、通信の送信者 Sender によって行われます。まず、送信するデータ Data に対してハッシュ Hash 混乱を行い、データの要約 Digest を得ます。その後、秘密鍵 Private Key を使って要約を暗号化し、これによりデータの署名が生成されます。
検証#
受信者 Receiver は、送信者からのデータと署名を受け取り、それぞれ以下の処理を行います:
- データ:送信者と同じハッシュアルゴリズムを使用してデータを混乱させ、データ要約 A を得る;
- 署名:送信者が使用した秘密鍵に対応する公開鍵 Public Key を利用して署名を復号し、データ要約 B を得る。
要約 A と要約 B を比較し、等しい場合はデータが改ざんされていないことを示し、そうでない場合はデータに問題があることを示します。
署名の生成と検証のプロセスは以下の図のようにまとめられています。自分で再分析することで理解を深めることができます。
問題を持って次に進む:
Q1: iOS 署名と検証のプロセスを推測してみてください。アプリ開発者とアプリ使用者の中で、誰が送信者で、誰が受信者で、伝送されるデータは何ですか?
A1: アプリ開発者が送信者で、アプリ使用者が受信者です。伝送されるデータはアプリのインストールパッケージです。
Q2: 受信者はどのように復号に使用する公開鍵を取得するのでしょうか?
次に進んでください。
デジタル証明書#
デジタル証明書について理解する前に、送信者がデータと署名を送信する際に公開鍵を添付すれば万事整うのではないかと思うかもしれません。以下の図のように:
しかし、これには新たな問題が生じます:
Q1: 受信者はどのようにして公開鍵が他の人によって悪意を持って置き換えられていないことを確認するのでしょうか?つまり、公開鍵の身元が不明です。
この時、デジタル証明書が登場します。
構成内容#
デジタル証明書の構成内容を見てみましょう。それは公開鍵、公開鍵の身元情報 Identity Info、およびそれらの署名 B で構成されています。
注意:暗号化された公開鍵データに使用される秘密鍵は、別の公開鍵 / 秘密鍵の組み合わせであり、権威ある認証機関(Certificate Authority, CA)によって発行されます。
公開鍵はデジタル証明書の中で伝送される#
これにより、送信者が送信する内容はデータ + 署名 +公開鍵から、データ + 署名 +証明書に変わります。
証明書には、受信者が署名 A を復号するために必要な公開鍵が含まれており、さらに証明書には公開鍵の身元情報と署名 B も含まれています:
- 身元情報の存在により、公開鍵の身元不明のリスクを排除できます;
- そして、署名 B は公開鍵およびその身元情報が改ざんされていないことを保証します。
しかし、署名 B があるため、公開鍵を取得する際には、まず証明書内の署名 B を検証する必要があります:
注意:証明書内の署名 B を復号するために使用される公開鍵も CA によって発行されており、CA 証明書内に存在します。
今、あなたは証明書の構成内容を覚えていると思います:公開鍵 + 公開鍵の身元情報 + それらの署名。
問題を持って次に進む:
Q1: 受信者はこの CA 証明書をどこで取得するのでしょうか?受信者はどのようにしてこの CA 証明書の署名を検証するのでしょうか?無限ループに入ったようです♻️。
次に進んでください。
証明書の信頼チェーン#
CA 証明書は一般的にシステム / ソフトウェアをインストールする際に内蔵されており、これで私たちはそれを信頼できるはずです~
次に、証明書の信頼チェーンについてさらに理解を深めましょう。
証明書が信頼チェーン内で占める位置に基づいて、証明書は 3 種類に分けられます:
- ルート証明書 Root Certificate(参考:Apple のオペレーティングシステムで利用可能な信頼されたルート証明書——Apple 公式)
- 中間証明書 Intermediate Certificate
- リーフ証明書 Leaf Certificate
例:私の開発者証明書 A(Apple Development)は、中間証明書 B(Apple Worldwide Developer Relations Certification Authority、Xcode インストール時に内蔵)によって発行され、中間証明書 B はルート証明書 C(Apple Root CA、システム内蔵)の CA によって発行され、ルート証明書 C は自分の CA によって発行されています。C は信頼チェーンの頂点にあるため、自分で決定します。
前の質問に戻りましょう:この CA 証明書が信頼できることをどうやって保証するのでしょうか?受信者が発行者の証明書を持っていれば、証明書内の公開鍵を使用して検証すれば良いのです。例えば、iPhone が私が開発したアプリをインストールする際、私の開発者証明書 A を受け取った場合、携帯電話は発行者の証明書 B(Apple Worldwide Developer Relations Certification Authority、iOS システム内蔵)を探して A が信頼できるかどうかを検証します。
今、あなたも自分の Mac > キーチェーン Keychain ソフトウェア > 証明書 Certificates を見て、理解を深めることができます。
問題を持って次に進む:
Q1: 暗号化された公開鍵およびその身元情報に使用される CA の秘密鍵は私たちのコンピュータにローカルに存在しますか?もしそうでない場合、私たちの証明書をどのように生成するのでしょうか?
iOS 証明書申請原理 & 申請方法#
もちろん、そうではありません。これらの秘密鍵は CA が証明書を発行するための秘密の宝物です。例えば、iOS 開発者証明書を申請したい場合、Apple 公式に手伝ってもらう必要があります。Apple 公式は、上記で言及した中間証明書 CA の秘密鍵を使用して証明書を発行します。
申請原理#
自分の iOS 開発者証明書を申請するには、以下のステップを踏む必要があります:
- 自分のコンピュータで公開鍵 / 秘密鍵ペアを生成し、公開鍵 / 秘密鍵ペアの身元情報を記入する;
- 公開鍵およびその身元情報を Apple CA に送信する;
- CA はハッシュアルゴリズムと CA の秘密鍵を使用してデータ(公開鍵およびその身元情報)に署名し、データと署名が私たちが望む証明書を構成します;
- 私たちは CA から証明書をダウンロードし、証明書をインストールすると、コンピュータは自動的に対応する秘密鍵を関連付けます。
申請方法:2 種類#
具体的な申請方法は 2 種類あります:1)CSR (CSR, Certificate Signing Request) ファイルをアップロードする方法、2)Xcode による自動申請方法。ここでは後者を推奨します。
1)CSR ファイルをアップロードする方法#
この方法は、iOS 証明書申請の原理を理解したいあなたに適しています。注意:この方法ではApple Developer Program に参加する必要があります、$99 / 年。
a) キーチェーンを開き、Certificate Assistant > Request a Certificate From a Certificate Authority... を選択:
b) 身元情報(メールアドレス、証明書名)を入力し、ローカルに保存することを選択できます。これにより、CSR (.certSigningRequest) ファイルが生成され、公開鍵およびその身元情報が含まれます。
あなたは、秘密鍵はどこにあるのかと疑問に思うかもしれません。もしあなたが注意深いなら、キーチェーン > login > Keys の中に、あなたが命名した公開鍵 / 秘密鍵ペアがすでに追加されていることに気づくでしょう。
c) Apple Developerのウェブサイトにログインし、Certificates, Identifiers & Profiles セクションに入り、先ほど生成した CSR ファイルをアップロードすることで証明書(.cer ファイル)が生成されます。この時、証明書をローカルにダウンロードし、ダブルクリックすることでキーチェーンにインポートできます。キーチェーン > login > My Certificates の中にその証明書が表示されます。
もしあなたが注意深いなら、キーチェーン内のその証明書はすでに秘密鍵とバインドされていることに気づくでしょう。他の開発者と証明書を共有したい場合は、右クリックしてお馴染みの.p12 ファイルをエクスポートする必要があります。これには証明書と対応する秘密鍵が含まれています~
2)Xcode 自動申請方法(推奨)#
この方法では、面倒な CSR ファイルのアップロードや.cer 証明書のダウンロードプロセスは必要ありませんし、Apple Developer Program への参加も強制されません。
a) Xcode で Apple アカウントにログインします:Xcode > Preference > Account > Apple IDs > 「+」。
b) ログイン後、キーチェーンに自動的に対応する証明書が追加されていることに気づくでしょう。
注意:もしあなたが開発者プログラムに参加している場合、Apple Developer のウェブサイトにも自動的にその証明書が追加されます。
iOS 署名 & パッケージング原理#
ついに iOS 署名の部分に来ました。前の内容は理解できましたか?もしまだ少し混乱しているなら、署名の役割は伝送されるデータの改ざんを防ぐことを覚えておけば、この記事の真髄を基本的に把握したことになります!
実際、iOS 署名を行う際には、証明書(公開鍵)を追加するだけではなく、証明書に対してもう一層の包装が必要です。それが私たちがよく知っている Provisioning Profile ファイルで、PP ファイル、プロファイル、供給設定ファイルとも呼ばれます。
PP ファイル#
この重要な PP ファイルについて理解しましょう。これを証明書のアップグレード版と考えることができます。
生成方法#
- 開発者プラットフォームで申請する;
- Xcode で自動生成する:Xcode > Targets > Signing & Capabilities > Automatically manage signing をチェック。
ファイル構造#

- App ID:
- Apple 開発者プラットフォームで登録する;または Xcode > Targets > Signing & Capabilities で記入した Bundle ID に基づいて自動生成される。
- Xcode > Targets > Signing & Capabilities で記入した Bundle Identifier は、App ID と一致またはマッチする必要があります。
- Entitlements:
- 使用可能な権限のリスト。実際にアプリで使用される権限は、このリストのサブセットでなければならず、Xcode > Targets > Signing & Capabilities で追加した Capabilities はその範囲を超えてはなりません。
- プロジェクトディレクトリ内にも.entitlements ファイル(権限ファイル)があり、これは Xcode > Targets > Signing & Capabilities で追加した Capabilities に基づいて自動生成されます。アプリがサンドボックス制限の機能を使用している場合、該当する権限がその.entitlements ファイルに宣言されていないと、アプリが関連するコードに到達した際に直接クラッシュします。
- Certificates:iOS 開発者証明書で構成され、複数存在することができます。これらは上記で申請した iOS 証明書です。
- Devices:iOS デバイスの UDID(Unique Device Identifier)で構成されたリストで、アプリの開発とデバッグが可能な iOS デバイスを制限します。
- Signature:PP ファイル生成時に Apple CA によって署名され、改ざんを防ぎます。
例#
PP ファイルはデフォルトで~/Library/MobileDevice/Provisioning\ Profiles
に保存されます。
以下は Xcode が自動生成した PP ファイルのプレビューです:
署名 & パッケージング#
iOS 署名とパッケージングのプロセスは実際には Xcode によって制御されます。以下の図を見てください:
- まず、Xcode はアプリ内の bundle ID が PP ファイル内の App ID と一致するか、アプリ内の Entitlements (.entitlements) ファイルで宣言された権限が PP ファイル内の Entitlements で許可された権限の範囲内にあるかを確認します。いずれかの条件が満たされない場合、チェックは通りません;
- 次に、Xcode はコンピュータのキーチェーン内に PP ファイル内の Certificates に証明書が一致するかを探します。一致した場合にのみ次のステップに進みます;
- その後、Xcode は一致した証明書が対応する秘密鍵にバインドされているかを確認します。もしそうでなければ、次の重要なステップである署名を行うことができません;
- さあ、ハッシュアルゴリズムと秘密鍵を使用してアプリに署名を開始します;
- 最終的に、アプリ、PP ファイル、および署名をパッケージングし、.ipa パッケージを生成します。
⚠️:上記では署名 C と署名 A の検証プロセスを省略しています。第 1 ステップで PP ファイルを使用する前と第 2 ステップで証明書が一致した後に、CA の公開鍵を使用してそれに付随する署名 C と A を検証する必要があります。改ざんを防ぐためです。誤りがあればご指摘ください。
延伸問題:
Q1: Xcode はアプリのどの内容に署名を行いますか?
A1: すべての内容です。しかし、署名プロセスは非常に複雑で、ここでは詳しく説明しません。簡単に言えば、署名の安全性と効率を考慮して、アプリの署名は 4 回のハッシュと 1 回の暗号化に分かれています。各ハッシュは連携しており、アプリの内容が改ざんされていないことを保証します。
具体的には、iOS コード署名の詳細(3):署名プロセスとコード署名のデータ構造を参照してください。
iOS 検証原理#
iOS 署名について話した後、実機がアプリをインストールする際にその署名をどのように検証するのでしょうか?
まず、アプリのインストールパッケージはテストパッケージと正式パッケージに分かれ、両者の検証プロセスは異なります。
ついでに、テストパッケージと正式パッケージについての知識を補足します:
1)テストパッケージ:内部テストパッケージ、App Store にアップロードするためのリリースパッケージ、Ad Hoc リリースパッケージ、In-house 企業内部リリースパッケージの 4 種類があります。
2)正式パッケージ:App Store にアップロードされたインストールパッケージです。
⚠️:Xcode が作成したパッケージはすべてテストパッケージに該当します。
参考:iOS の異なるタイプのテストパッケージの紹介—— 搜狗テスト公式アカウント。
テストパッケージ#
テストパッケージをインストールする際、実機は完全な検証プロセスを実行します。以下の図を参照してください:
- まず、実機はシステム内蔵の CA 公開鍵を使用してPP ファイルおよびその署名 C の合法性を検証します;
- 次に、実機はシステム内蔵の CA 公開鍵を使用して PP ファイル内の証明書およびその署名 A の合法性を検証します;(アプリ内には署名 B を生成するために使用された証明書情報が保存されているため、実機はどの証明書から公開鍵を取得するかを知ることができます)
- その後、実機は証明書内の公開鍵を取り出し、アプリおよびその署名 B の合法性を検証します;
- 最後に、実機は自分の UDID が PP ファイルの Devices リストに存在するかを確認し、存在する場合にのみアプリのインストールを開始します。
⚠️:図では検証プロセスが簡略化されていますが、あなたはこのプロセスに非常に慣れているはずです。ハッシュ混乱、公開鍵復号、判定...
実際、署名の検証は一度で完了するものではなく、インストール、起動、実行時に異なる検証ルールがあります。上記はそのプロセスを簡略化したもので、具体的には細説 iOS コード署名(4):署名検証、脱獄、再署名を参照してください。
正式パッケージ#
正式パッケージをインストールする際、実機の検証プロセスは大幅に簡略化されます。なぜなら、開発者証明書の検証プロセスは App Store に委ねられるからです。
1)リリースパッケージを App Store にアップロードします。
- リリースパッケージ(テストパッケージの一種)を App Store にアップロードすると、Apple 公式もリリースパッケージの検証を行います。そのプロセスは上記のテストパッケージの検証プロセスに似ています;
- 検証が通過すると、App Store はアプリに再署名を行います。この時、使用されるのは開発者証明書に対応する秘密鍵ではなく、CA の秘密鍵です;
- 最後に、App Store はアプリと新しい署名をパッケージングし、.ipa パッケージを生成します。(⚠️:PP ファイルは含まれていません)
2)実機が正式パッケージをインストールします。
デバイスが App Store からアプリをダウンロードすると、システム内蔵の CA 公開鍵を使用してアプリを検証し、検証が通過すればインストールが可能です。
練習してみましょう#
インターネット上には非常に良い図がいくつかありますので、番号に従ってプロセスを振り返り、この記事の内容を強化してください。
出典:iOS 証明書に関する事柄—— 掘金。
出典:iOS アプリ署名の原理——Blog。
本文の目的に戻る#
最後に、記事の冒頭で提起した問題に戻り、それらの問題を解決する前に常に 2 つのものを心に留めておいてください:秘密鍵を含む証明書(.p12 = .cer + private key)、PP ファイル(.mobileprovision)。
再度、私たちの問題を見てみましょう。上記の 2 つのものを見つけるだけで済みます:
- 実機で自分の iOS プロジェクトや iOS オープンソースライブラリを実行するにはどうすればよいか?
- 秘密鍵を含む証明書:iOS 証明書申請方法のセクションを参照;
- PP ファイル:開発者プラットフォームで申請;または Xcode で自動生成、Targets > Signing & Capabilities > Automatically manage signing をチェック。
- 実機で会社の iOS プロジェクトを実行するにはどうすればよいか?
- 秘密鍵を含む証明書:チームから入手、ファイルの拡張子は.p12 であることに注意;
- PP ファイル:チームから入手、責任者に自分の実機の UDID を PP ファイルに追加してもらうことを忘れないでください。
PS:
- テストパッケージでインストールしたアプリを実行する際、実機で証明書を信頼する必要がある場合があります:Settings > General > VPN & Device Management。
- Xcode が自動生成した PP ファイル:
参考資料#
全体を把握する:iOS 証明書の背後にある原理——Blog
深く理解する:iOS コード署名の詳細——Blog
その他、あなたが興味を持つかもしれない:
- iOS 証明書とプロファイルの申請——DClound
- iOS アプリのリリース方法は何ですか?—— 知乎
- iOS 再署名の探求—— 簡書