Skip to main content

HMAC-SHA256 Signature Verification

All webhook payloads between adapters and ZenEdge are signed using HMAC-SHA256 to ensure authenticity and integrity.

Algorithm

  1. Take the raw JSON payload body
  2. Compute HMAC-SHA256 using the shared secret
  3. Hex-encode the digest
  4. Compare with the signature in the header
X-Webhook-Signature: sha256=a1b2c3d4e5f6...

Implementation Examples

Node.js

const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}

Python

import hmac
import hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)

Go

package main

import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
)

func verifySignature(payload []byte, signature, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(payload)
expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(signature), []byte(expected))
}

Security Best Practices

  • Always use timingSafeEqual (or equivalent) to prevent timing attacks
  • Verify the signature before parsing the JSON payload
  • Store the shared secret securely (environment variable, not in code)
  • Rotate secrets periodically

Next Steps