> For the complete documentation index, see [llms.txt](https://docs.qwaap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.qwaap.com/webhooks-and-redirects/webhooks/rsa-signature-verification.md).

# RSA Signature Verification

## Download the Public Key File

Download the public key file for the specific environment by clicking the link below and store it somewhere on your server

**Production**

{% embed url="<https://qwaap.ams3.cdn.digitaloceanspaces.com/certs/qwaapprod.public.key.pem>" %}

**Sandbox**

{% embed url="<https://qwaap.ams3.cdn.digitaloceanspaces.com/certs/qwaap.public.key.pem>" %}

## Next Steps

Below is the sample callback data for this demonstration

```json
{
    "id": 2061,
    "request_amount": 10000,
    "request_currency": "UGX",
    "transaction_fee": 1000,
    "total_credit": 9000,
    "invoice_number": "QINVNHNU4FMGMHBKA8YQ",
    "merchant_reference": "1184",
    "payment_status": "PAID",
    "transaction_type": "COLLECTION",
    "status_message": "Invoice payment successful"
}
```

1. Obtain the value of the `rsa-signature` header.
2. Form the string payload to be used in signature verification. This is obtained by concatenating values of the callback data in the format; `id:invoice_number:payment_status:merchant_reference`and these values are obtained from the callback data. The string payload would therefore be 2061`:`QINVNHNU4FMGMHBKA8YQ`:`PAID`:`1184
3. Use the public key obtained above to verify the signature as described in the sample source codes below;&#x20;

{% tabs %}
{% tab title="PHP" %}

```php
<?php

public function isValidSignature() {
    $file = "path-to-file/qwaap.public.key.pem";
    $keyContent = file_get_contents($file);
    $publicKey = openssl_get_publickey($keyContent);
    $strPayload = "2061:QINVNHNU4FMGMHBKA8YQ:PAID:1184";
    $signature = base64_decode("value-of-rsa-signature");

    /*true or false*/
    return openssl_verify($strPayload, $signature, $publicKey, "sha512") == 1;
}

?>
```

{% endtab %}

{% tab title="NodeJS" %}

```javascript
const crypto = require('crypto');
const fs = require('fs');

function isValidSignature() {
    const strPayload = "2061:QINVNHNU4FMGMHBKA8YQ:PAID:1184";
    const signature = "value-of-rsa-signature";
    const publicKeyFile = "path-to-file/qwaap.public.key.pem";
    const publicKey = fs.readFileSync(publicKeyFile).toString().replace(/\\n/g, '\n');

    const verify = crypto.createVerify("SHA512");
    verify.write(strPayload);
    verify.end();

    /*true or false*/
    return verify.verify(publicKey, signature, 'base64');
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
A valid signature for the above sample callback is shared below. You can copy and use it to test your signature verification workflow.
{% endhint %}

```
QnxX3OtP8IHj0BtdPCshNBZJnCBH9PowDVUxJzXNe9vDsZj1TOiE64XoYqVAEFRXsry/SMwtIjUC6WVYC21AWMVLmc4nb9l3g5i9Tca+Rw1vYuK6Let50/JotM0EsiJr/V8GgM2YBsTISF6FA6/f7fcjaDYg681r2Y2pWbNDz1acmCOH4uhWVWncoyHu+VYXDhQN+F8aUVhOVk1xcnXAR5dtNh9NFNXCM4vWWRcP6QACt7A4lD706Suj4xC4BZrk4WZ3gKLx8SRRrVY1LEgkOEXiUYvJf4JINpmVUoCCltld14dvGpS5xschdlQgSLGE0cr2oGkEdkUSd6eO9yIO8buEJoliFMbtH/BcMf4qTcIBx4C/0i/sB+Gr2OWr4mcmhQxFEMK1ioTNDYKi5J9xbcPpJiDP6lIK6QWWaxSxXZ03yAxHNQCaK9GBfyX0cZUGDFpJw3lA4Gz4X2B1lKDH1ze3xMhKVSheEwtytpMWmF5TIL0+o1gFWNCST5V7BfD9IbUje6lUVRoYX7GhMcVyDVdpQIEazH7nPIbL/qHCMkTEDyCc1ySQoZuDbCL02+O8sDp4KQrN9uPrfME0NPqIy3QRyhbbaWxvzvgMhUIhWYCaGxfOaHf1prTu42R2Z6Q385j8SC48JmtZ/6fvoIIThuOItnZq1HH6vOcfBadvZeY=
```
