SSL証明書のCAを正しく選ぶべき理由

Apple Webhook設定中に発生した問題とその原因分析


Apple IDの退会などのイベントが発生すると、Appleは私たちのサービスにHTTPリクエストを送信するWebhook機能を提供しています。
apple2ourserver

これを利用すれば、Apple IDが削除された際に、私たちのサービスのアカウントも自動的に休眠状態にすることができます。

問題の発生

AppleのダッシュボードでWebhookエンドポイントを登録するだけで完了すると思っていました。
しかし、Webhookリクエストがまったく届きませんでした。

興味深いことに、ngrokWebhookテストサイト では正常にリクエストが届いていました。
apple2otherserver

WAFやホワイトリスト(17.0.0.0/8)の設定も正しいことを確認しました。

何が違うのか?

では、私たちのAPIサーバーとWebhookテストサービスの間にはどんな違いがあったのでしょうか?
SSLに問題があると疑い、SSLテストサイトで確認しました。

すると、「Trusted(信頼性)」の項目でJavaが赤く表示されていたのです。
sslchecker_trusted

まさにここに問題の原因がありました。

SSL通信の仕組みを理解する

Trusted」とは、クライアントがサーバー証明書を信頼できるかどうかを示す状態を意味します。
これを理解するために、SSL通信の流れを段階的に整理してみましょう。

1. 準備段階

ssl_step1

  1. CA(認証局)は公開鍵と秘密鍵のペアを生成します。
  2. クライアントは信頼できるCAのリストを保持します。
    • OS、Mozilla、Javaなど、それぞれ独自のTrust Store(信頼ストア)を持っています。

2. 証明書発行と設定

ssl_step2

  1. サーバーは自分の鍵ペアを生成し、公開鍵をCAに送ります。
  2. CAはサーバーの公開鍵をハッシュ化し、自身の秘密鍵で署名して証明書を発行します。
  3. サーバーはCAが発行した証明書を設定します。

CA署名」とは、CAがサーバーの公開鍵を検証し署名したものを指します。

3. クライアントとサーバーの通信

ssl_step3

  1. クライアントはサーバーにSSL接続を要求します。
  2. サーバーは証明書をクライアントに送信します。
  3. クライアントは証明書のCA署名を検証します。
    • このとき、クライアントは自分のTrust Storeに保存されているCAの公開鍵を使用します。
  4. 検証が完了すると、両者は通信に使用する共通鍵(対称鍵)を交換します。
  5. その共通鍵でデータを暗号化・復号して通信を行います。

非対称暗号では、公開鍵で暗号化されたデータは秘密鍵で、秘密鍵で暗号化されたデータは公開鍵で復号できます。

通信エラーの原因

私たちが使用していた証明書のCAは、JavaのTrust Storeに含まれていませんでした
AppleのWebhookクライアントはJavaで実装されており、Javaが信頼しないCAの証明書とはSSL接続できません。

つまり、Javaクライアントの視点では、私たちのサーバー証明書は「信頼できない状態」だったのです。

まとめ

  1. 使用するCAによっては、一部のクライアントが証明書を信頼しない場合があります。
  2. 今回のケースでは、韓国電子認証TuringSignの公開鍵がJavaのTrust Storeに含まれておらず、通信エラーが発生しました。
  3. Java環境やグローバルサービスと通信する可能性がある場合は、DigiCertLet’s Encryptなど、広く信頼されているCAを選ぶのが安全です。
    • ちなみに、Let’s Encryptは無料で利用できます。