
ウェブプッシュにおける鍵の利用方法
WebPush では、ブラウザ、各サーバのそれぞれが公開鍵・秘密鍵ペアを生成し、署名や暗号化処理に使われます。このため、他のプラットフォームと異なり、通知を送るアプリの事前登録が必要なく、プラットフォームのサーバに通知の内容を読まれてしまうこともありません。
しかし、同じような鍵ペアが色々な場所で出現するため最初は容易に取り違える可能性がありますし、それぞれ何をするための鍵なのかを知っておいたほうが鍵管理にも役立ちます。
仕様関連
WebPush の仕様は RFC8030 に書かれていますが、これには認証や暗号化を含みません。通知を送信する場合に送信者を認証する仕組みとして、古い Chrome は GCM(Google Cloud Messaging) を使った認証を行なっていましたが、現在は VAPID (RFC8292) という方法が使えるようになりました。また、通知メッセージの暗号化は RFC8291 で公開されており、これらの仕様を組み合わせて使います。
用語の定義
各種仕様書によると、ブラウザやサーバは以下のような名称で定義されています。
ユーザエージェント
通知を受け取るブラウザのこと。現在はChrome 52以降、Firefox 48以降、Edge 42以降、またはそれらを利用したカスタムブラウザがWebPushに対応しています。
プッシュサービス
ユーザエージェントへ実際に通知を行うサービスのこと。現状はGoogle、Mozilla、Microsoftがそれぞれ提供する3つのサービスが存在します。
アプリケーションサーバ
サードパーティの開発者が作成するプッシュサービスへ通知を依頼するサーバ。通知をしたい場合に開発者が実装するべきサーバで、BoltzEngineはこれに該当します。
アプリケーションサーバが生成する鍵ペア
アプリケーションサーバが管理する鍵ペアは2つ存在します。
VAPID 用の鍵ペア
1つ目の鍵ペアは、VAPID で認証を行うために使います。Web Push を有効にした時、ユーザエージェントは公開鍵を参照してデバイストークンの払い出しを行います。デバイスへ通知を行う際に、アプリケーションサーバは対応する秘密鍵を使って署名をします。プッシュサービスは署名を使って認証を実施します。
トークン生成時の公開鍵と、通知送信時の秘密鍵がペアになっていれば良いので、事前にプッシュサービスへ鍵を登録する必要はありません。また、BoltzMessenger では1つのペアしか使いませんが、ユーザエージェントごとに鍵ペアを生成しても問題ありません。
暗号化用の鍵ペア
2つ目の鍵ペアは、通知メッセージの暗号化で利用します。アプリケーションサーバの秘密鍵と、ユーザエージェントの公開鍵を使ってメッセージの暗号化を行います。
実際は鍵を使って、アプリケーションサーバとユーザエージェントでお互いに共通鍵を生成し、共通鍵で暗号化を行いますが、この共通鍵が表に現れることはありません。
ユーザエージェントが生成する鍵ペア
ユーザエージェントが生成する鍵ペアは、通知を有効化した場合に p256dh
として公開鍵だけ取得可能です。上記でも書きましたが、この公開鍵は auth
で取得する乱数と共にアプリケーションサーバへ渡し、アプリケーションサーバは通知メッセージの暗号化を行うために利用します。
鍵の交換方法
公開鍵はどのように交換されるかをまとめます。
アプリケーションサーバ-VAPID用の公開鍵
ユーザエージェントには任意の方法で送信し、JavaScript 上で PushManager.subscribe
の options
引数に渡すディクショナリの applicationServerKey
に指定します。
VAPID 検証のために、プッシュサービスへ Crypto-Key: p256ecdsa=
ヘッダで送信します。
アプリケーションサーバ-暗号化の公開鍵
プッシュサービスへ Crypto-Key: dh=
ヘッダを使って暗号化したメッセージと共に送信します。
ユーザエージェントの公開鍵
アプリケーションサーバへ任意の方法で送ります。この部分は規定されていないため、どのような手段でも構いません。
BoltzMessenger では、デバイストークンの一部としてトークン登録APIへ送信します。