# Signature Validation

Remember the mail man scenario we shared earlier in comparison with how webhooks work. Imagine you are the busy kind of person, and you receive quite a lot of parcels. We believe you cannot identify who sent what parcel (JSON Data) by just looking at the envelope.&#x20;

Yeah, there is always a signature that acknowledges the sender. Our webhooks work like that too.

Moreover, who knows? An unfriendly person might be cooking something unhealthy for you.&#x20;

### Handling WebHook Requests

Our notifications often carry a `x-browpay-signature` header. This header is a `HMAC SHA512` signature that is signed using your secret key.

&#x20;It is important to verify your webhook requests against fake or unrelated data before it is processed for security purposes.&#x20;

{% tabs %}
{% tab title="Node JS" %}

<pre class="language-javascript" data-overflow="wrap"><code class="lang-javascript">const crypto = require('crypto');

const secret = your-secret-key;
// Using ExpressJS
app.post("/your-server/webhook-endpoint", (req, res) =>  {
   //validate event    
<strong>   const hash = crypto.createHmac('sha512', secret).update(JSON.stringify(req.body)).digest('hex');
</strong><strong>   if (hash == req.headers['x-browpay-signature']) {
</strong><strong>   // body
</strong><strong>   const event = req.body;
</strong><strong>   // you may use the data here
</strong><strong>   }
</strong><strong>   
</strong><strong>   // do nothing
</strong><strong>res.send(200);
</strong><strong>
</strong><strong>});
</strong></code></pre>

{% endtab %}

{% tab title="Python" %}

```python
import hmac
import hashlib
from http.server import BaseHTTPRequestHandler, HTTPServer

class WebhookHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        secret = b'your-secret-key'
        content_length = int(self.headers['Content-Length'])
        content = self.rfile.read(content_length)

        # validate event
        hash_signature = hmac.new(secret, content, hashlib.sha512).hexdigest()
        if hash_signature == self.headers.get('x-browpay-signature'):
            # process the event
            event = content.decode('utf-8')
            # use the data here

        # do nothing
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b'OK')

if __name__ == '__main__':
    server_address = ('', 8000)
    httpd = HTTPServer(server_address, WebhookHandler)
    httpd.serve_forever()
```

{% endtab %}

{% tab title="JAVA" %}

```java
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class MinimalWebhookHandler {

    public static void main(String[] args) throws IOException {
        int port = 8080;
        HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
        server.createContext("/your-server/webhook-endpoint", new WebhookHandler());
        server.setExecutor(null); // creates a default executor
        server.start();
    }

    static class WebhookHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            InputStream requestBody = exchange.getRequestBody();
            byte[] buffer = new byte[1024];
            int bytesRead;
            StringBuilder content = new StringBuilder();

            while ((bytesRead = requestBody.read(buffer)) != -1) {
                content.append(new String(buffer, 0, bytesRead));
            }

            requestBody.close();

            // Your secret key
            String secret = "your-secret-key";
            // validate event
            String hash = generateHash(content.toString(), secret);
            if (hash.equals(exchange.getRequestHeaders().getFirst("x-browpay-signature"))) {
                // process the event
                String event = content.toString();
                // use the data here
            }

            // do nothing
            exchange.sendResponseHeaders(200, 0);
            OutputStream os = exchange.getResponseBody();
            os.close();
        }

        private String generateHash(String data, String secret) {
            // Implement your HMAC generation logic here
            return ""; // Replace with your actual implementation
        }
    }
}

```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

$secret = 'your-secret-key';
$content = file_get_contents('php://input');
$hash_signature = hash_hmac('sha512', $content, $secret);

if ($hash_signature == $_SERVER['HTTP_X_BROWPAY_SIGNATURE']) {
    // process the event
    $event = $content;
    // use the data here
}

// do nothing
http_response_code(200);
echo 'OK';

```

{% endtab %}

{% tab title="GO" %}

```go
package main

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"io/ioutil"
	"net/http"
)

func main() {
	secret := "your-secret-key"

	http.HandleFunc("/your-server/webhook-endpoint", func(w http.ResponseWriter, r *http.Request) {
		content, _ := ioutil.ReadAll(r.Body)
		defer r.Body.Close()

		// validate event
		hash := generateHash(content, []byte(secret))
		if hash == r.Header.Get("x-browpay-signature") {
			// process the event
			event := string(content)
			// use the data here
		}

		// do nothing
		w.WriteHeader(http.StatusOK)
	})

	http.ListenAndServe(":8080", nil)
}

func generateHash(data []byte, secret []byte) string {
	h := hmac.New(sha512.New, secret)
	h.Write(data)
	hashBytes := h.Sum(nil)
	return base64.StdEncoding.EncodeToString(hashBytes)
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
We however added an extra layer of data security to protect you and the notification you receive from us. It is not recommended if you are satisfied with validating the signature.&#x20;

Payload Encryption and Decryption.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developer.browpay.com/webhooks/signature-validation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
