# 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 %}
