Recepção e Validação de Assinatura HMAC-SHA256 em Webhooks

Para certificar que os payloads de eventos recebidos em seu endpoint foram originados legitimamente pelos servidores da Yzex Tech, cada requisição HTTP POST inclui o cabeçalho de assinatura criptográfica X-Yzex-Signature.

Formato do Cabeçalho

O cabeçalho X-Yzex-Signature contém a assinatura HMAC gerada com o algoritmo SHA-256 sobre o corpo bruto (raw payload) da requisição, formatada em hexadecimal:

X-Yzex-Signature: sha256=a1b2c3d4e5f6...
X-Yzex-Timestamp: 1725960000

Algoritmo de Validação (Node.js / TypeScript)

import * as crypto from 'crypto';

export function verifyWebhookSignature(
  rawBody: string | Buffer,
  signatureHeader: string,
  secret: string
): boolean {
  if (!signatureHeader || !signatureHeader.startsWith('sha256=')) {
    return false;
  }

  const expectedSignature = signatureHeader.slice(7);
  const calculatedSignature = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  // Comparação em tempo constante para prevenir timing attacks
  const expectedBuffer = Buffer.from(expectedSignature, 'hex');
  const calculatedBuffer = Buffer.from(calculatedSignature, 'hex');

  if (expectedBuffer.length !== calculatedBuffer.length) {
    return false;
  }

  return crypto.timingSafeEqual(expectedBuffer, calculatedBuffer);
}

Recomendações de Resiliência

  • Armazenamento de Raw Body: Certifique-se de obter o corpo da mensagem como Buffer ou string bruta antes de qualquer processamento por parsers JSON intermediários.

  • Prevenção de Replay Attacks: Inspecione o cabeçalho X-Yzex-Timestamp e descarte eventos com discrepância temporal superior a 300 segundos.