Open11

iOSアプリの証明書まわりの話をしっかりと理解する

Yutaka KonoYutaka Kono

ここの図の方が登場人物の関係という意味では掴みやすい

https://dev.classmethod.jp/articles/apple-certificates-summary-and-etc/

  • 開発するMacで生成したCertSigningRequestをADP(Apple Developer Program)に登録して、ADP側で発行された証明書(Certificates)をダウンロードする。
  • 自機(Mac)で生成したCSRから取得したCertificatesを開発するMacのキーチェーンに登録することで開発者本人の本人性を証明していることになる(っぽい)
  • これとは別にADPでDevicesとApp IDを登録する。Devicesは開発中の実機ビルドをに使うiPhoneなどの端末
  • ADP側で登録されているCertificates、Devices、App IDの情報をバインド(?)したものがProvisioning Profile
  • Provisioning Profileを開発するXcodeプロジェクトの中で登録(設定)し、登録されてる開発者本人が、許可されたアプリ(許可されたApp ID)の開発において許可された端末(Devices)を向き先としたビルドであれば、ビルドしたipaファイルの実機へのインストールが許可される仕組み
Yutaka KonoYutaka Kono

そもそも論、iOS云々ではなく一般的な「鍵」「署名」「証明書」とかについて体系的に理解した方が良いっぽいので、調べた。記事にするより本の形にした方が良い?

暗号化とは

  • インターネットでデータを送信する際に様々なネットワークや機器を介する
  • その過程で第三者にデータを盗み見(盗聴)される可能性があるため、送信する前に送るデータを暗号化して送信し、受け手は暗号化されたデータを復号することで安全にデータを受け取る
  • コンピュータで扱うデータはすべて2進数の形式で扱われている。暗号化とは対象のデータと「鍵」と呼ばれるデータを何かしらの演算をすることで直接は読み取れない形式に変換すること
  • 復号とは、暗号化されたデータと鍵を何かしらの演算をすることで直接読み取れる形式に復元すること

公開鍵暗号化方式

  • 公開鍵暗号化方式とは暗号化と復号する際に異なる鍵を使う暗号方式のこと
  • 暗号化と復号で共通の鍵を用いる共通鍵暗号化方式も存在するが、その場合暗号化した鍵を復号のために相手に安全に届ける必要がある。鍵そのものを盗聴された場合、第三者によって暗号を復号されてしまう問題がある(鍵配送問題)。公開鍵暗号方式は暗号化と復号に用いる鍵が異なるため、暗号化した際の鍵を相手に渡す必要がなく、鍵配送問題が発生することがない。

公開鍵暗号化方式での通信

  • 共通鍵暗号化方式でのやり取りの流れは以下の通り
    1. データの送信前に受け取り手が公開鍵Pと秘密鍵Sを作成する
    2. このうち公開鍵Pを送り手にネットワークを介して送信する
    3. 送り手は受け取った公開鍵を使ってデータを暗号化し、送信する
    4. 受け取り手は暗号化されたデータを自分があらかじめ保持している秘密鍵で復号する
  • 上のやり取りの場合、第三者は 「2. このうち公開鍵Pを送り手にネットワークを介して送信する」と「4. 受け取り手は暗号化されたデータを自分があらかじめ保持している秘密鍵で復号する」の過程で公開鍵Pと暗号化されたデータを入手できる可能性があるが、公開鍵Pでは暗号化されたデータを復号することはできないため、データを盗聴されることはない。
  • また、公開鍵は上記の理由で不特定多数の人間に配布しても問題がないため、複数の人間とやり取りする場合でも利用することができる。送り手毎に鍵を生成する必要もない。

公開鍵の信頼性について

  • 公開鍵暗号化方式には鍵配送問題による問題は発生しないものの公開されている公開鍵の信頼性についての問題が発生する。
  • たとえば以下の手順で公開鍵が第三者にすり替えられた場合、第三者がデータを盗聴できる可能性がある。
    1. 送り手A・受け取り手Bがデータをやり取りするときに悪意のある第三者Xがいる場合を考える
    2. Bが公開鍵Pbと秘密鍵Sbを作成し、公開鍵PbをAに対して送信する。
    3. このとき、Xも公開鍵Pxと秘密鍵Sxを作成し、公開鍵Pbを送信する通信を盗聴し、公開鍵Pbと公開鍵Pxをすり替える
    4. Aは受け取った公開鍵Pxを使ってデータを暗号化し、Bに暗号化したデータを送信する
    5. Xが4.の通信を盗聴し、秘密鍵Sxを使って復号し、データを読み取った後公開鍵Pbを使って暗号化し、Bに対して暗号化したデータを送信
    6. Bは秘密鍵Sbを使ってデータを復号することで、Aから送信されたデータを通常通り受け取ることができる。
  • 上の問題(man-in-the-middle攻撃)は公開鍵に対して受け取り手が作成した鍵であることの本人性を証明できないことが原因で起こってしまうものである。この問題を解決するために公開鍵の作成者の本人性を証明する「デジタル署名」「デジタル証明書」が必要になるという話になる。
Yutaka KonoYutaka Kono

デジタル署名

  • デジタル署名とはデータを送受する時に、認証と改竄の検出に加えて否認防止も保証する仕組みのこと
  • ここでの署名とは、送信するデータから生成される暗号の一種のこと。暗号化する際には共通鍵暗号化方式を用いる。
  • データそのものを暗号化する際には暗号化に共通鍵、復号に秘密鍵を用いたが、署名を作成する際には署名の作成(暗号化)に秘密鍵、署名の検証(復号)に公開鍵を使用する。[1]
  • 復号は公開鍵を入手すれば誰でもできるので、この手法で生成された暗号は暗号としての意味はないものの、この暗号を生成できるのは秘密鍵を持っている人のみなのである。
  • 送信された署名が公開鍵で復号できることが、その署名が秘密鍵の持ち主が作成したことを証明していることになる。

デジタル証明書

  • デジタル証明書とは前段で説明した公開鍵の作成者を保証する仕組みのことを指している
  • 公開する鍵は認証局と呼ばれる機関から証明書を発行してもらう。
  • 公開鍵を公開する人間は公開鍵とメールアドレスなどの個人情報を含むデータを送信し、認証局からの署名を作成してもらう。
  • 署名の後に認証局から公開鍵・個人情報・認証局の署名を含むファイルを受け取る。そのファイルが公開鍵のデジタル証明書になる。
  • 証明書を受け取った公開鍵の作成者(A)は公開鍵の代わりに証明書を公開する。
  • 受け取り手は証明書と証明書に署名した認証局が公開している公開鍵を入手する。証明書の署名を認証局の公開鍵で検証して、証明書に含まれる公開鍵の本人性を検証する。
  • 認証局が公開している公開鍵も正確には証明書として公開されている。認証局の証明書はより上位の認証局が署名して作成される。認証局と呼ばれる機関は複数あり、基本誰でもなれるものだが、認証局全体が木構造を構成していて、下位の認証局の本人性を上位の認証局が保証する仕組みができている。
脚注
  1. 厳密には署名の作成とデータの「暗号化」では共通鍵暗号化方式の秘密鍵・共通鍵を用いるという点は同じだが、計算方法が異なる。余力があれば調べる。 ↩︎

Yutaka KonoYutaka Kono

これらを踏まえると

  • ADPが発行する証明書のうち
    • 開発用・本番用の証明書:審査に提出したりするipaファイルの作成者の本人性を証明するための証明書
    • PUSH通知用証明書:PUSH通知を送信する送信元がアプリの配信元であることの証明(PUSH通知の送信元の本人性の証明)

みたいに考えれば良い?

Yutaka KonoYutaka Kono

公開鍵暗号化方式を理解したらこの図の意味がわかるようになった&もっともこれが理解しやすい。

https://qiita.com/fujisan3/items/d037e3c40a0acc46f618

ADPに発行してもらう証明書には、開発用(Development)と配布用(Distribution)の2種類がある。さらに、それぞれの証明書に紐付いたProvisoning Profileが生成される。
用途はそれぞれ以下の通り

  • 開発用:検証用の実機でビルドする際に開発元の本人性を証明する
  • 配布用:App Storeで配布 or Ad-Hocで組織内部に配布する際に開発元の本人性を証明する

https://qiita.com/yosshi4486/items/7dbd7e2bc35a1fc9e5a0

Yutaka KonoYutaka Kono

↑の「パッケージ全体を秘密鍵でコードサイニング」の部分について

  • コードサイニング(署名)に使う秘密鍵はどこからくるのか?
  • 署名の検証に使う公開鍵はどこから持ってくるのか?というかそもそも本当に公開鍵使うよね...?

の2つが分からなかったけど、ちょっと分かった

  • コードサイニング(署名)に使う秘密鍵はどこからくるのか?
  1. CSRを生成したタイミングで秘密鍵も生成されて、ローカル(Mac)のキーチェーンアクセスの内部で管理されている
  2. CSRをアップロードして、署名を受けた証明書.cer をダウンロードした後、「書き出し」を実行した際に生成される.p12(Signing Indentity)の中に証明書の情報と秘密鍵が含まれている。
  3. Xcode上で設定する(Provisioning Profileを設定すると一意に決定する)Singing Certificateに入るSingning Indentityに含まれる秘密鍵を使うようになっている
  • 署名の検証に使う公開鍵はどこから持ってくるのか?というかそもそも本当に公開鍵使うよね...?
  • 開発用の検証端末で署名の検証をする場合
    Xcodeがデバイスにアプリをインストールする際にProvisioning Profileも同時に渡してて、Profileに含まれる証明書に含まれる公開鍵で検証する?[1]
  • App Store Connectにアップロードした後にApple側が検証する場合
    CSRを受け取り生成したProfileに含まれる証明書に含まれる公開鍵で検証する?

https://qiita.com/muijp/items/88567365dde2a3b3cc92
https://scrapbox.io/tasuwo-ios/Xcode_と署名
https://medium.com/ios-os-x-development/ios-code-signing-provisioning-in-a-nutshell-d5b247760bef
https://qiita.com/toto_kit/items/df84cd687919ec28591b

脚注
  1. Xcode will sign the App and push Provisioning Profiles onto the Device とあるので、アプリ本体とは別に切り離して、デバイスに送ってるんじゃないかな...と思ってる ↩︎

Yutaka KonoYutaka Kono

現状、調べた情報をまとめた

Yutaka KonoYutaka Kono

この図で入れられてないもの

  • .p12 と .p8の違い
  • Provisioning Profile(Development)とProvisioning Profile(Distribution)の違い
  • ADPとADEPについて(これに直接は関係ないけど)
Yutaka KonoYutaka Kono
  • Provisioning Profile(Development)とProvisioning Profile(Distribution)の違い

Provisioning ProfileがDevelopmentとDistributionに分かれているのではなく、Provisioning Profileに紐付ける証明書(Certificates)が開発用(Development)と配布用(Distribution)で分かれている。Certificatesを生成するときにどちら用にするかを選ぶ。