{
  "schema_version": "1.0.0",
  "record_type": "citation-evidence-pack",
  "pack_id": "webhook-signature-verify",
  "title": "Webhook signature verification evidence",
  "description": "Byte-exact HMAC outcomes for a valid signature, a raw-body/signature mismatch, and a malformed provider header.",
  "scope": "These cases prove deterministic comparison behavior for disclosed synthetic secrets. They do not receive webhooks or establish sender identity.",
  "canonical_url": "https://encrypt-online.com/evidence/webhook-signature-verify.json",
  "tool": {
    "id": "webhook-signature-verify",
    "name": "Webhook Signature Verifier",
    "path": "/tools/webhook-signature-verify",
    "canonical_url": "https://encrypt-online.com/tools/webhook-signature-verify"
  },
  "implementation": {
    "version": "source-sha256:291dced379f090ab",
    "aggregate_sha256": "291dced379f090ab5e30da245e440443bcdec19637ac198d73dda2e99321930a",
    "sources": [
      {
        "path": "lib/webhook-signature-core.mjs",
        "sha256": "8c19a791d9bab46b45e633638bd97b959d8218868831bbf71deaf94da90ef38c"
      },
      {
        "path": "lib/hmac-tools-core.mjs",
        "sha256": "cb9eada995e5a3cb824908dcab458afdfc60a1cb67ce9496760198b34b7078e8"
      },
      {
        "path": "lib/browser-security-fixtures.mjs",
        "sha256": "77c7622557ad876d4c62b09a18ffb3d4f71374081ae44a8487282620f916557f"
      }
    ]
  },
  "verification": {
    "last_verified": "2026-08-05",
    "command": "npm run check:citation-evidence",
    "environments": [
      "Node.js release check with Web Crypto",
      "Chromium desktop 1440x900 evidence presentation"
    ]
  },
  "standards": [
    {
      "name": "HMAC",
      "section": "Definition and construction",
      "url": "https://www.rfc-editor.org/rfc/rfc2104"
    },
    {
      "name": "GitHub webhook validation",
      "section": "Validating webhook deliveries",
      "url": "https://docs.github.com/en/webhooks/using-webhooks/validating-webhook-deliveries"
    }
  ],
  "cases": [
    {
      "case_id": "WEBHOOK-HMAC-VALID-001",
      "classification": "valid",
      "symptom": "A provided generic HMAC matches the exact synthetic raw body.",
      "safe_input": {
        "provider": "generic",
        "secret": "shared-secret",
        "body": "payload=alpha&timestamp=1711641000",
        "algorithm": "sha256",
        "encoding": "hex",
        "signature": "97266f38792d3eecb63676c05df3a7b8477964e796da7025c4f159bdd7f67a81"
      },
      "expected_output": {
        "status": "match",
        "expected_digest": "97266f38792d3eecb63676c05df3a7b8477964e796da7025c4f159bdd7f67a81",
        "signing_string": "payload=alpha&timestamp=1711641000"
      },
      "failure_code": null,
      "expected_outcome": "Accept the byte-level comparison, subject to the provider's replay and secret-selection policy.",
      "fixture_sha256": "8112e7a5eae20eaeb5b730b118b38c24fe9d202c4a22e14b43898f8f3a86719d"
    },
    {
      "case_id": "WEBHOOK-HMAC-MISMATCH-002",
      "classification": "mismatch",
      "symptom": "The supplied digest does not match the digest of the exact synthetic raw body.",
      "safe_input": {
        "provider": "generic",
        "secret": "shared-secret",
        "body": "payload=alpha&timestamp=1711641000",
        "algorithm": "sha256",
        "encoding": "hex",
        "signature": "87c222f0cdc3d96c8d32e764cbc36da3d0fbd17441a60bc30c38a9648e9fca2f"
      },
      "expected_output": {
        "status": "mismatch",
        "expected_digest": "97266f38792d3eecb63676c05df3a7b8477964e796da7025c4f159bdd7f67a81",
        "signing_string": "payload=alpha&timestamp=1711641000"
      },
      "failure_code": "SIGNATURE_MISMATCH",
      "expected_outcome": "Reject and compare the raw bytes, secret, algorithm, and encoding.",
      "fixture_sha256": "4e72de76d2e6ae544aa5df2c93eabbb16def53ec64b3ba20041afcc28da77edc"
    },
    {
      "case_id": "WEBHOOK-GITHUB-HEADER-MALFORMED-003",
      "classification": "malformed",
      "symptom": "A GitHub-style header names an unsupported sha512 prefix.",
      "safe_input": {
        "provider": "github",
        "body": "{}",
        "secret": "synthetic",
        "signature_header": "sha512=bad"
      },
      "expected_output": {
        "status": "rejected",
        "message": "GitHub headers must look like sha256=<hex> or sha1=<hex>."
      },
      "failure_code": "INVALID_SIGNATURE_HEADER",
      "expected_outcome": "Reject before HMAC comparison.",
      "fixture_sha256": "ede347196d4b5e414c7fa81695672f17094ec4b88d3d26f9469f2fabac0326f2"
    }
  ]
}
