いわゆるWebhooksは、改ざん防止のためのハッシュをつけることができる。
それを受け取り側で検証するコードはこういう風に書くっていうメモ。Node.jsの場合は調べればいっぱい出てくるけど、最近のWorker環境系ではズバリなやつが見つからなかったので。
コード
const encoder = new TextEncoder(); /** * @param {string} signature * @param {[string, string]} payloadAndSecret * @returns {Promise<boolean>} */ const verifySignature = async (signature, [payload, secret]) => { const key = await crypto.subtle.importKey( "raw", encoder.encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["verify"] ); const verified = await crypto.subtle.verify( "HMAC", key, hexToBytes(signature), encoder.encode(payload) ); return verified; /** * @param {string} hex * @returns {ArrayBuffer} */ function hexToBytes(hex) { const bytes = new Uint8Array(hex.length / 2); for (let c = 0; c < hex.length; c += 2) bytes[c / 2] = parseInt(hex.substring(c, c + 2), 16); return bytes.buffer; } }; const handleFetch = async (req, env, _ctx) => { const signature = req.headers.get("X-Hub-Signature-256") ?? "N/A"; const payload = await req.text(); // sha256=xxx... const verified = await verifySignature(signature.slice(7), [ payload, env.GITHUB_WEBHOOK_SECRET, ]); if (!verified) return new Response("Not Found", { status: 404 }); const push = JSON.parse(payload); // ... };
GitHubのWebhooksはSHA256のほうが推奨らしいのでそっちを使って検証する。肝心のところはWeb Cryptoに丸投げ。
いったん`text()`で受け取って、あとで`JSON.parse()`するのがなるほどなって感じ。