' Reemplaza "NombreDelModulo" con el nombre de tu módulo
Sub Process_Globals
Private BC As ByteConverter ' Necesita la librería ByteConverter
End Sub
' Inicializa ByteConverter en Sub Globals o un lugar apropiado
' BC.Initialize
' Función para calcular el HMAC-SHA256 (necesario para la verificación)
' Retorna la firma calculada en formato Hexadecimal (ajustar si es Base64)
Private Sub CalculateHmacSha256(Message As String, Key As String) As String
' Se requiere la librería Encryption (o acceso a java.security.*)
Dim kg As KeyGenerator
Dim m As Mac
' 1. Inicializar KeyGenerator con el algoritmo HMACSHA256
' El secreto debe convertirse a bytes (generalmente UTF8)
kg.Initialize("HmacSHA256")
kg.KeyFromBytes(Key.GetBytes("UTF8"))
' 2. Inicializar Mac con la clave generada
m.Initialise("HmacSHA256", kg.Key)
' 3. Calcular el hash del mensaje (cuerpo RAW del webhook)
' El mensaje debe convertirse a bytes (generalmente UTF8)
m.Update(Message.GetBytes("UTF8"))
' 4. Obtener la firma como array de bytes
Dim SignatureBytes() As Byte = m.Sign
' 5. Convertir el array de bytes a una cadena (Hexadecimal es común)
Return BC.HexFromBytes(SignatureBytes).ToLowerCase
End Sub
' Función principal de validación
' SignatureHeader: El valor completo del encabezado X-Webhook-Signature
' Payload: El cuerpo RAW de la solicitud HTTP (sin parsing previo)
' Secret: La clave secreta de firma proporcionada por el servicio
Public Sub ValidateWebhookSignature(SignatureHeader As String, Payload As String, Secret As String) As Boolean
' 1. Extraer la firma real del encabezado
' El formato del encabezado puede variar (ej: t=timestamp,v1=signature)
' **AJUSTA ESTA PARTE según el formato EXACTO de tu proveedor**
Dim ExpectedSignature As String ' La firma extraída del encabezado
' Asumiremos por simplicidad un formato simple "X-Webhook-Signature: <firma>"
' Si el formato es complejo (ej: Stripe, GitHub), esta lógica debe extraer
' la parte de la firma y el timestamp, y el payload a firmar puede incluir el timestamp.
ExpectedSignature = SignatureHeader ' Si es solo la firma en el encabezado
' --- EJEMPLO para un encabezado con prefijo 'sha256=' (común) ---
If SignatureHeader.StartsWith("sha256=") Then
ExpectedSignature = SignatureHeader.SubString(7) ' Elimina el prefijo "sha256="
Else If SignatureHeader.StartsWith("v1=") Then
' Asume que la firma sin prefijo es la que hay que comparar
' **REVISA TU DOCUMENTACIÓN**
ExpectedSignature = SignatureHeader.SubString(3) ' Elimina el prefijo "v1="
End If
' -------------------------------------------------------------------
' 2. Calcular la firma local
Dim CalculatedSignature As String
' **IMPORTANTE**:
' Algunos servicios (ej: Stripe) firman: timestamp + "." + payload.
' Otros solo firman el payload RAW.
' Debes usar EXACTAMENTE el string que tu proveedor de webhooks firma.
' Si solo se firma el payload:
CalculatedSignature = CalculateHmacSha256(Payload, Secret)
' Si se firma timestamp + "." + payload (ajusta la extracción de timestamp en el paso 1)
' Dim TimeStamp As String ' (extraído del encabezado)
' CalculatedSignature = CalculateHmacSha256(TimeStamp & "." & Payload, Secret)
' 3. Comparar las firmas
' Se usa String.EqualsIgnoreCase para ser más flexible, pero la comparación de Hex debe ser exacta.
' Se recomienda una comparación a tiempo constante para prevenir ataques de tiempo (aunque no es trivial en B4A).
Return CalculatedSignature.EqualsIgnoreCase(ExpectedSignature)
End Sub
' Ejemplo de uso:
' Dim IsValid As Boolean = ValidateWebhookSignature(ReceivedSignatureHeader, RawRequestBody, "your_webhook_secret_key")
' If IsValid Then
' Log("Firma Válida")
' Else
' Log("Firma Inválida")
' End If