iOS 構成プロファイルの署名

# とりあえず初めに

署名されている = 信頼できる安全なものってわけではない事に注意
署名済みプロファイルを入れさせようとするフィッシングサイトも出てきています。

佐川急便を騙り、デバイス登録チャレンジペイロードを含むプロファイル。
一般的にはMDM（iOSの遠隔監視ツール）の登録をさせようとするもの。
インストールを完了させなくても、デバイス情報をサーバに送る場合があります。というか送る仕様のプロファイル。
Apple Developerの証明書による署名をしているため、検証済みとなってしまっています。

<img width="375" alt="38EA01A0-F481-4B84-B4F9-BF533FFA2BB3.png" src="https://qiita-image-store.s3.amazonaws.com/0/143797/fb45b841-19da-2046-e6fb-d1aaf86c0fb1.png">
<img width="375" alt="F4CCEBED-6709-444C-883F-92FA4ECA9DE3.png" src="https://qiita-image-store.s3.amazonaws.com/0/143797/eabf92b6-5070-6a1b-c6ed-0be1ec78a172.png">

## 構成プロファイル署名の目的

「その構成プロファイルが誰によって作成されたものか」を明示することと、「署名された以降に内容を改竄（書き換え）されていないか」を保証するもの。
繰り返しとなるが「署名されている = 信頼できる安全なもの」ではない。署名されていても内容が危険な場合はある。

署名された構成プロファイルが「検証済み」となっている場合は、その証明書がiOSが保持しているCAによって署名された正しい証明書であることを検証しているのみである。
プロファイルの中身まで検証しているわけではないので、署名されていても内容が危険な場合はある。
詐欺サイトやフィッシングサイトで「SSL化されているから安心安全ね」ってわけじゃないのとだいたい同じ。

いわゆる「オレオレ証明書」で署名してあっても、そのルート証明書を予めiOSに入れておけば「検証済み」となるし、未検証であったとしても、署名されている証明書のフィンガープリントを確認するなどして署名者を特定したうえでその署名者を信用するのであればある意味検証済みと同義と考えていいかもしれない。

Apple Developerの証明書は金さえ出せば容易に入手でき、たぶん本人確認とか無いので信用しちゃいけないかも知れない。上の画像とか、「誰だよJohn Gabriel？」ってな話
企業名でのApple DeveloperアカウントはDUNS番号での企業認証があるのでまだマシ。でも知らない企業名のとかはもちろん信用しちゃいけない。

## Apple Configurator 2を用いた署名
- [ファイル]→「プロファイルに署名...」を選択して、署名IDを選択。
  ![スクリーンショット 2016-10-09 12.14.30.png](https://qiita-image-store.s3.amazonaws.com/0/143797/efda343f-ce53-c251-3330-8facac9ec2a9.png)
  ![スクリーンショット 2016-10-09 12.14.40.png](https://qiita-image-store.s3.amazonaws.com/0/143797/f71c967a-9af4-f700-626c-f378bf05ed5d.png)
  ![スクリーンショット 2016-10-09 12.14.49.png](https://qiita-image-store.s3.amazonaws.com/0/143797/54d57691-8f87-06f6-341e-717b4012e4b7.png)
  ![スクリーンショット 2016-10-09 12.14.55.png](https://qiita-image-store.s3.amazonaws.com/0/143797/650cee2b-dd19-0d41-583e-8bca0187646a.png)

- 組織識別情報を作成している場合は、それを用いて署名が可能。
    - ただし自己署名ルート証明書となり、iOS側では未検証となる。
        - iOSに信頼済み証明書として登録することで回避できるが、不特定多数への配布に向かない。

### Apple Configurator 2を用いた署名解除

署名を削除する場合は、[ファイル]→「プロファイルの署名を削除」を選択。
![スクリーンショット 2016-10-09 12.15.05.png](https://qiita-image-store.s3.amazonaws.com/0/143797/2e56b539-7427-800f-7d4f-09e6ec4fdcdf.png)


### Apple Configurator 2で署名ができない場合

前項の「署名ID」で証明書が出てこなくて署名ができない場合
署名するためには鍵用途（Key Usage）に「デジタル署名（Digital Signature）」が含まれていないとリストに出てこない様子。
なのでオレオレ証明書とかでプロファイルに署名をしたい場合は、そのように作るか、次項のOpenSSLを使って署名する。
なお、俺々証明書を作る場合は[XCA](https://hohnstaedt.de/xca/)を[使え](https://qiita.com/hirohero/items/a4bfeae7d860eb7dbd8a)ば楽かも知れない。
っていうかもうちょっとイイ感じのPKI管理は無いものか。。。

## OpenSSLを用いた署名
macOS Sierra, OpenSSL 0.9.8zh 14 Jan 2016

```bash
$ openssl smime -sign -nodetach \
-signer [証明書].cer \
-inkey [秘密鍵].key \
-in [未署名プロファイル入力元].mobileconfig \
-out [署名プロファイル出力先].mobileconfig \
-outform der
```

### SSL証明書を用いてOpenSSLで署名例
有効な証明書を用いれば、検証済みプロファイルとして扱われる。
（Let's Encryptでも可能だが、有効期限が短いため使いづらいか）
その場合は、チェーン証明書を追加する必要がある。

```bash
$ openssl smime -sign -nodetach \
-signer [証明書].cer \
-inkey [秘密鍵].key \
-certfile [チェーン証明書].cer \
-in [未署名プロファイル入力元].mobileconfig \
-out [署名プロファイル出力先].mobileconfig \
-outform der
```

但し、プロファイルへの署名はコードサイニングに近しいため、特に有料SSL証明書の場合は使途外利用にあたらないか確認が必要

### OpenSSLを用いた署名済みプロファイルの証明書確認

```bash
$ openssl pkcs7 \
-in [署名済みプロファイル入力元].mobileconfig \
-inform der \
-print_certs
```

### OpenSSLを用いた署名解除

```bash
$ openssl smime -verify -noverify \
-in [署名済みプロファイル入力元].mobileconfig \
-inform der \
-out [署名解除プロファイル出力先].mobileconfig
```

## macのkeychainに入っている鍵で署名

```zsh
$ security cms -S \
-i [未署名プロファイル入力元].mobileconfig \
-o [署名プロファイル出力先].mobileconfig \
-N "[Keychain証明書名]"
```

### 署名解除

```zsh
$ security cms -D \
-i [署名済みプロファイル入力元].mobileconfig \
-o [署名解除プロファイル出力先].mobileconfig 
```

## 署名済みプロファイルのサンプル入手元

別記事「[構成プロファイルの削除コントロールといまさらながらixintpwn（YJSNPI）の削除方法の没ネタ](https://qiita.com/garupon/items/91421d42b05a8a946829)」のために作成した「[上のプロファイル（署名版）](https://goo.gl/byKd1L)」か、[「iOS14 encrypted DNS(DNS over TLS, DNS over HTTPS)」の「参考元とか」](https://qiita.com/garupon/items/00b22cbf2d1d7c13d703#%E5%8F%82%E8%80%83%E5%85%83%E3%81%A8%E3%81%8B)にある「[iOS 14でAdGuard DNSを使う方法 | AdGuard](https://adguard.com/ja/blog/encrypted-dns-ios-14.html)」に署名されたプロファイルが転がっている。
前者は期限切れ。後者はiOS14以上対象だが署名を見るだけなら14未満でも見られる。

## プロファイル毎のiPhone上での表示

- 未署名
  <img width="375" alt="IMG_0079.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/143797/bc872e85-2786-447e-3465-0b7b84c89cb6.png">
  インストール中に「未署名のプロファイル：このプロファイルは署名されていません」の警告

- 自己署名
  <img width="375" alt="IMG_0080.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/143797/8b441767-9f67-6ee7-e5b8-5eb0ed9e9f2f.png">
  <img width="375" alt="IMG_0082.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/143797/7bc3e217-d3db-8eda-741d-66ddb8c5574d.png">
  インストール中に「未検証のプロファイル："[プロファイル名]"の真正性を確認できません」の警告

- SSL証明書
  <img width="375" alt="IMG_0081.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/143797/7174e6cb-ae20-6d9b-ee1c-3070068c04a6.png">
  <img width="375" alt="IMG_0083.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/143797/023c5426-bac6-b95a-cf5f-eb06dc500297.png">

## 個人的まとめ

あくまで、プロファイルを署名することの目的は「作成者の明示」と「改竄の防止」である。プロファイルの中身が信頼できるものであることを保証するものではない。
正規の証明書で署名することで、インストール時の赤字表示や警告を無くすことができ、プロファイル自体の改ざんを防ぐ事が可能ではある。
だが、証明書の有効期限が切れてしまった場合はiOS側で期限切れの警告表示となり、警告を消すためだけに更新作業を行ったり、期限切れ警告を無視するよう利用者に案内することを考慮すると最初から署名しない選択肢もアリなのかもしれない。
各キャリアのメールやWi-Fiのプロファイル、MVNO各社のAPNプロファイルも未署名だし、一概に無署名は悪、信頼署名が正義って事でも無い。

だからと言って、未署名のプロファイルを配ると結局ユーザーがビビるし、「警告出るけどそのままインストールしてね」とされると危機感が薄れる。
Appleさん、せめて期限切れ問題をなくすためにもPDFみたくタイムスタンプ署名とかできないもんですかね？
あともうちょっと詳しく署名方法を公式に出しておいていただけないもんですかね？

### よく調べていないこと

署名されたプロファイルの更新は、同一の証明書（もしくは同一CN）で署名されたものでのみ更新が可能っぽいが試していない。
プロファイル識別子が同一であっても、未署名or異なる署名のプロファイルで更新を試みた場合は「先にプロファイルを削除してください」と警告が出て更新ができない。
意図しないプロファイルの差し替えを防ぐ仕様として好ましいのではあるが、YJSNPIのような不正プロファイルが署名されていたら手の打ちようがなくなる。

### おまけ

署名はあくまで署名なので、メールやWi-Fi、VPNのパスワード類はすべて平文のまま。
パスワードを伏せるのであれば、暗号化プロファイルの利用を。

正式に署名して運用をする場合は、オレオレ証明書やSSL証明書ではなくサイニング証明書を使うべき。普通のSSL証明書を使ってしまうと用途外利用で怒られるかもしれない。

<!-- 正直、このページを引き合いに出して「簡単にできるんだから署名しろよ」とキャリアやMVNOに突撃しないでほしい -->