// engine/webhook/signature.ts — HMAC-SHA256 signature validation for Lemon Squeezy webhooks.
// Validates the X-Signature header against the raw request body.
import { createHmac, timingSafeEqual } from 'node:crypto';
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const SIGNATURE_HEADER = 'x-signature';
const HMAC_ALGO = 'sha256';
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Validates an HMAC-SHA256 signature from a Lemon Squeezy webhook request.
 * Uses timing-safe comparison to prevent timing attacks.
 *
 * @param rawBody - The raw request body bytes (NOT parsed JSON)
 * @param signatureHeader - The value of the X-Signature header
 * @param secret - The webhook secret configured in Lemon Squeezy dashboard
 * @returns true if signature is valid, false otherwise
 */
export function validateSignature(rawBody, signatureHeader, secret) {
    if (!secret || !signatureHeader) {
        return false;
    }
    const expectedHex = createHmac(HMAC_ALGO, secret).update(rawBody).digest('hex');
    try {
        const expectedBuf = Buffer.from(expectedHex, 'hex');
        const receivedBuf = Buffer.from(signatureHeader, 'hex');
        if (expectedBuf.length !== receivedBuf.length) {
            return false;
        }
        return timingSafeEqual(expectedBuf, receivedBuf);
    }
    catch /* v8 ignore start */ {
        return false;
    } /* v8 ignore stop */
}
/**
 * Extracts the signature header value from a map of HTTP headers.
 * Header names are case-insensitive in HTTP/1.1.
 */
export function extractSignatureHeader(headers) {
    const raw = headers[SIGNATURE_HEADER];
    if (Array.isArray(raw)) {
        return raw[0] ?? '';
    }
    return raw ?? '';
}
//# sourceMappingURL=signature.js.map