IDピン留め:アプリのサーバ証明書を設定する方法
2021年1月14日
アプリがネットワークを介してデータを送受信する場合、個人情報のプライバシーと整合性を維持し、データ侵害や攻撃から保護することが重要です。Transport Layer Security (TLS)プロトコルを利用し、転送中のコンテンツを保護し、データを受信するサーバを認証する必要があります。
注:証明書のピン留めは必須ではありません。ピン留めの設定は慎重に検討し、どうしても必要な場合にのみ実施してください。
TLSを介して接続する場合、サーバはIDを確立するために証明書または証明書チェーンを提供します。さらに、アプリに公開キーIDをピン留めすることで、アプリが信頼するサーバ証明書のセットを制限することができます。ここでは、その方法を紹介します。
ピン留めを使用するタイミング
ピン留めは大半の場合不要です。できるだけその使用を避けてください。通常、アプリが安全なTLSネットワークに接続すると、システムはデフォルト設定によりサーバの信頼性を評価します。大半のアプリは、この動きに依存することでセキュリティ要件を満たすことができます。しかし、特定のアプリでは、信頼できる証明書セットのさらなる制限する必要があります。
たとえば、アプリは信頼できるCertificate Authorities(CA)を決定する規制要件を満たすことが必要な場合があります。Appleプラットフォームでは、デフォルトで信頼できるCAのみが関与することが保証されていますが、アプリではIDピン留めを使用して、CAのセットを関連付けられている特定の政府や組織にさらに制限することができます。
ピン留めはアプリの信頼要件を緩めることはできず、厳しくすることしかできません。TLSネットワーク接続に関係する公開キー証明書を使用する場合でも、システムのデフォルトの信頼要件を常に満たす必要があります。
注: 所定のサーバへの特定の公開キーセットを予期してアプリを設定する場合、それらの公開キーが関与しない限り、そのサーバへの接続を拒否します。その結果、サーバが公開キーを変更する新しい証明書を展開すると、アプリは接続を拒否します。その時点で、新しい公開キーのセットを反映するピン留め設定でアプリを更新する必要があります。
長期的に考える
アプリでIDピン留めを使用したい場合は、ピン留めの失敗を防ぐために、計画的なイベントと計画外のイベントの両方を考慮した、長期的な戦略を立てることを検討してください。
アプリは、サーバではなくCAの公開キーをピン留めすることで、すばらしい経験を積極的に提供することができます。このように、ピン留め設定を更新することなく、同じCAによって署名された、新しい公開キーを含むサーバ証明書を展開できます。
特にサーバIDをピン留めする場合は、複数の公開キーをピン留めすることも考慮できます。このように、証明書を失効またはローテーションする場合でも、設定済みのサーバに接続することができます。
さらに、ピン留め失敗の場合は、サーバに接続できない場合は、アプリでバックアップを準備することを計画してください。まず、アプリの経験がどのように影響を受けるかを考えると、悪影響を軽減するを提案します。接続を行わなくてもアプリは機能し、ユーザーに一時的な回復パスを提供できますか? 最終的な復旧パスを計画しておく必要もあります。ピン留めの失敗に対処できる方法の1つに、アプリの変更によって提供される新しいピン留め設定を採用することです。Appのユースケースに応じて、それがオプションかどうかを検討してください。
この目的のために追加の公開キー証明書を取得し、それに応じてサーバの設定を変更することにより、アプリをテストする際、さまざまなイベントと潜在的な障害点をシミュレーションすることを強くお勧めします。
CA公開キーをピン留めする方法
ピン留めされたCA公開キーは、中間証明書かルート証明書のどちらかの証明書チェーンに表示されなければなりません。ピン留めされたキーは常にドメイン名に関連付けられていて、アプリはピン留め要件を満たさない限り、そのドメインへに接続することを拒否します。
例として、 example.org
ドメイン名に接続する際、特定のCA公開キーを要求するには、アプリのInfo.plist
ファイルに下記のエントリを追加することができます。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSPinnedDomains</key>
<dict>
<key>example.org</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSPinnedCAIdentities</key>
<array>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=</string>
</dict>
</array>
</dict>
</dict>
</dict>
この例では、ピン留めされた公開キーは example.org
と math.example.org
や history.example.org
などのサブドメインに関連付けられていますが、advanced.math.example.org
や ancient.history.example.org
には関連付けられていません。
公開キーは、X.509証明書のDERエンコードされたASN.1 Subject Public Key Info構造のBase64エンコードされたSHA-256ダイジェストとして表されます。ファイル ca.pem
に格納されている以下のPEMエンコードされた公開キー証明書を想定すると、openssl
コマンドでSPKI-SHA256-BASE64値を計算することができます。
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
$ cat ca.pem | openssl x509 -inform pem -noout -outform pem -pubkey | openssl pkey -pubin -inform pem -outform der | openssl dgst -sha256 -binary | openssl enc -base64
冗長性をピン留め設定へ導入するために、複数の公開キーをドメイン名に関連付けることができます。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSPinnedDomains</key>
<dict>
<key>example.org</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSPinnedCAIdentities</key>
<array>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=</string>
</dict>
</array>
</dict>
<key>example.net</key>
<dict>
<key>NSPinnedLeafIdentities</key>
<array>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>i9HaIScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI=</string>
</dict>
<dict>
<key>SPKI-SHA256-BASE64</key>
<string>i9HaIScvf6T/skE3/A7QOq5n5cTYs8UHNOEFCnkguSI=</string>
</dict>
</array>
</dict>
</dict>
</dict>
例えば、example.net
サーバ証明書の複数の公開キーをピン留めするには、アプリの Info.plist
ファイルに配列内の項目として個々のエントリを追加します。example.net
への接続のピン留め要件を満たすには、サーバ証明書はそれらのキーの一つを含まなければなりません。