署名検証は、その通知やデータが本当に正しい送り主から来たものかを確かめる処理です。 とくに Webhook ではかなり重要で、受け取ったリクエストが本物かどうかを判断する土台になります。
まず押さえたいポイント
- 送り主確認のための処理
- Webhook や外部連携でかなり重要
- これがないと偽物の通知を受け入れる危険がある
どんな場面で使うか
- Stripe や GitHub などの Webhook 受信
- 外部サービスからの通知受け口
- 改ざんされていないか確認したい連携処理
どんなふうに理解するとよいか
初心者向けには、差出人確認つきの通知 と考えると入りやすいです。
見た目が同じ HTTP リクエストでも、正しい送り主からのものかは別で確認しないと分かりません。
押さえておきたい注意点
URL を知っているだけで誰でも叩ける状態にしてしまうと、偽の完了通知や勝手なイベント実行につながることがあります。
そのため、署名やシークレットを使った確認を入れて、検証に失敗したら処理を進めないのが基本です。
仕組み:どうやって本物と判断するのか
多くのサービスはHMACという方式を使います。送信側は事前に共有した秘密の文字列(シークレット)+送信内容から署名を計算し、ヘッダーに載せて送ります。受信側は同じ計算をして一致するかを確かめます。
秘密の文字列を知らなければ正しい署名を作れないので、①送り主が本物であること ②中身が改ざんされていないことを同時に確認できます。
実装でハマりやすい点
- 署名は「生のリクエストボディ」で計算する。フレームワークがJSONを解析して再構築したものを使うと、空白や順序の差で一致しなくなる
- 単純な文字列比較を避ける。比較にかかる時間差から署名を推測される可能性があるため、タイミング安全な比較関数を使う
- タイムスタンプも一緒に検証する。署名が正しくても、過去の正規リクエストをそのまま再送されると通ってしまう(リプレイ攻撃)ため、古すぎるものは拒否する
- 検証に失敗したら即座に拒否し、本体処理へ進まない
実務で見るポイント
Webhook の受け口はURLを知っていれば誰でも叩けます。署名検証が無いと、偽の「決済完了」通知で商品を発送してしまうといった実害に直結します。シークレットは環境変数などで管理し、コードに直接書かないのが前提です。